Skip to content

Commit b0cee89

Browse files
author
Steve Coffman
committed
Add vault command and update docs
1 parent a977463 commit b0cee89

File tree

8 files changed

+120
-28
lines changed

8 files changed

+120
-28
lines changed

README.md

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This will download the github 0.1.0 binary release for mac, and move any of your
1414
keyfob add [name] [key]
1515
keyfob otp [name]
1616
keyfob list
17+
keyfob vault [name] [profile]
1718
keyfob help
1819

1920
+ `keyfob add name` adds a new key to the keyfob keychain with the given name. It
@@ -29,7 +30,9 @@ clipboard.
2930

3031
+ `keyfob list` prints the names of all the added keys, if any.
3132

32-
The time-based authentication codes are derived from a hash of the
33+
+ `keyfob vault [name] [profile]` acts as a will act as an [AWS credential helper](https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes) using [AWS Vault](https://github.com/99designs/aws-vault/) and a One Time Password.
34+
35+
The Time-based One Time Password (TOTP) authentication codes are derived from a hash of the
3336
key and the current time, so it is important that the system clock have at
3437
least one-minute accuracy.
3538

@@ -51,9 +54,10 @@ Then whenever GitHub prompts for a 2FA code, run keyfob to obtain one:
5154
$ keyfob otp github
5255
268346
5356

54-
## Derivation
57+
## Derivation (Credit where Credit is due)
5558

5659
This is just a little toy cobbled together from [2fa](https://github.com/rsc/2fa/), [cobra](https://github.com/spf13/cobra), and [go-keyring](https://github.com/zalando/go-keyring) and using [goreleaser](https://github.com/goreleaser/goreleaser).
60+
The directions I had below this were confusing, so I stole some of the directions from [this article on how to do a similar thing with a yubikey](https://hackernoon.com/use-a-yubikey-as-a-mfa-device-to-replace-google-authenticator-b4f4c0215f2).
5761

5862
## Really, does this make sense?
5963

@@ -91,37 +95,50 @@ keyring frontend program [Seahorse](https://wiki.gnome.org/Apps/Seahorse):
9195

9296
This assumes you have installed `keyfob` but need to set up your secrets.
9397

94-
Your own organization __*might*__ have a different preferred `source_profile` name from `sosourcey` below.
98+
__*Note:*__ Your own organization __*might*__ have a different preferred `source_profile` name from `source` below, and your AWS account number is probably not `111111111111`.
9599

96100
1. Skip to **[2](#2)** if you already added your AWS access key and secret access key to aws vault. Otherwise do this:
97101
```
98-
$ aws-vault add sosourcey --keychain login
102+
$ brew cask install aws-vault
103+
$ brew install go zbar awscli
104+
$ aws-vault add source --keychain login
99105
```
100-
2. <a name="2"></a>Go to AWS, and [make a new MFA token](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_virtual.html#enable-virt-mfa-for-iam-user). Either take a screenshot of the QR Code (⌘⇧3 aka Command-Shift-3) and run `zbarimg` on it as below, or click the option to see the text version. Save that secret somewhere. Also add it to your Google Authenticator as normal.
106+
107+
2. <a name="2"></a>Go to the AWS Web console to [make a new MFA token](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_virtual.html#enable-virt-mfa-for-iam-user).
108+
109+
3. After login, go to IAM > Users and click in your user name. Then you need to click on the “Security credentials” tab.
110+
<img src="./images/aws_iam_users_security_credentials.png" />
111+
112+
4. To assign an MFA device, just click Manage. If you have an existing one, you must remove it. In the next screen, select “Virtual MFA device”.
113+
<img src="./images/manage_virtual_mfa_device.png" />
114+
115+
5. Here you can choose to show the QR code or to show the text of the MFA secret key. For our purposes, we want the secret key only.
116+
<img src="./images/get_mfa_secret_key.png" />
117+
118+
6. Add your MFA secret (from above) to keyfob:
101119
```
102-
brew cask install aws-vault
103-
brew install go zbar awscli
104-
# To get the text secret out of the QR Code if you didn't ask to see that
105-
zbarimg AWS_IAM_Management_Console.png
120+
keyfob add aws-source <YOUR_BASE_32_KEY>
106121
```
107-
3. Copy the `aws-credential-helper.sh` script in this repository to a place in your shell path and remember the absolute path to there.
108122

109-
4. Add to your `.aws/config` file something like this:
123+
7. Then run `keyfob otp aws-source` a few times, to get two different, but consecutive 6-digit codes and complete the set up.
124+
<img src="./images/mfa_setup_correctly.png" />
125+
126+
8. Add to your `.aws/config` file something like this:
110127
```
111128
[default]
112-
credential_process = /Users/scoffman/bin/aws-credential-helper-engineer.sh
129+
credential_process = keyfob vault aws-source engineer
113130
region = us-east-1
114131
output = json
115132
116-
[profile sosourcey]
133+
[profile source]
117134
region = us-east-1
118135
mfa_serial = arn:aws:iam::111111111111:mfa/scoffman
119136
120137
[profile engineer]
121138
mfa_serial = arn:aws:iam::111111111111:mfa/scoffman
122139
region = us-east-1
123140
role_arn = arn:aws:iam::111111111111:role/put-power-role-here
124-
source_profile = sosourcey
141+
source_profile = source
125142
```
126-
5. Make sure you've edited and replaced the AWS account, userid, and power-role above.
143+
9. Make sure you've edited and replaced the AWS account, userid, and power-role above.
127144

cmd/otp.go

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import (
3333
var otpCmd = &cobra.Command{
3434
Use: "otp [key name]",
3535
Short: "Generate a One Time Password",
36-
Long: `otp name prints a two-factor authentication code from the key with the given name.
36+
Long: `otp [key name] prints a two-factor authentication code from the key with the given name.
3737
If -clip is specified, otp also copies to the code to the system clipboard.
3838
With no arguments, otp prints two-factor authentication codes from all known time-based keys.
3939
@@ -44,26 +44,37 @@ so it is important that the system clock have at least one-minute accuracy.`,
4444

4545
service := "keyfob"
4646
user := args[0]
47-
secret, err := keyring.Get(service, user)
47+
48+
codeText, err := generateTOTP(service, user)
4849
if err != nil {
4950
log.Fatal(err)
51+
return
5052
}
51-
raw, err := decodeKey(secret)
52-
if err == nil {
53-
code := totp(raw, time.Now(), 6)
54-
codeText := fmt.Sprintf("%0*d", 6, code)
55-
56-
if clip {
57-
clipboard.WriteAll(codeText)
58-
}
5953

60-
fmt.Printf("%s\n", codeText)
61-
return
54+
if clip {
55+
clipboard.WriteAll(codeText)
6256
}
63-
log.Printf("%s: malformed key", secret)
57+
//fmt has no prefix, log does
58+
fmt.Printf("%s\n", codeText)
59+
6460
},
6561
}
6662

63+
func generateTOTP(service, user string) (string, error) {
64+
secret, err := keyring.Get(service, user)
65+
if err != nil {
66+
return "", err
67+
}
68+
raw, err := decodeKey(secret)
69+
if err != nil {
70+
return "", fmt.Errorf("%s: malformed key", secret)
71+
}
72+
code := totp(raw, time.Now(), 6)
73+
codeText := fmt.Sprintf("%0*d", 6, code)
74+
75+
return codeText, nil
76+
}
77+
6778
var clip bool
6879

6980
func init() {

cmd/vault.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Copyright © 2019 NAME HERE <EMAIL ADDRESS>
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package cmd
17+
18+
import (
19+
"fmt"
20+
"log"
21+
"github.com/spf13/cobra"
22+
"os/exec"
23+
)
24+
25+
// vaultCmd represents the vault command
26+
var vaultCmd = &cobra.Command{
27+
Use: "vault [key name] [aws profile]",
28+
Short: "AWS credential helper using AWS Vault and Time-based One Time Password",
29+
Long: `"vault [key name] [aws profile] will act as an AWS credential helper using
30+
AWS Vault and Time-based One Time Password
31+
Ref: https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#sourcing-credentials-from-external-processes`,
32+
Args: cobra.ExactArgs(2),
33+
Run: func(cmd *cobra.Command, args []string) {
34+
service := "keyfob"
35+
user := args[0]
36+
profile := args[1]
37+
codeText, err := generateTOTP(service, user)
38+
if err != nil {
39+
log.Fatal(err)
40+
return
41+
}
42+
out, err := exec.Command(
43+
"aws-vault", "exec", "--mfa-token="+codeText, "-j", profile).CombinedOutput()
44+
fmt.Println(string(out))
45+
if err != nil {
46+
log.Fatalf("aws-vault returned %v", err)
47+
}
48+
},
49+
}
50+
51+
func init() {
52+
rootCmd.AddCommand(vaultCmd)
53+
54+
// Here you will define your flags and configuration settings.
55+
56+
// Cobra supports Persistent Flags which will work for this command
57+
// and all subcommands, e.g.:
58+
// vaultCmd.PersistentFlags().String("foo", "", "A help for foo")
59+
60+
// Cobra supports local flags which will only run when this command
61+
// is called directly, e.g.:
62+
// vaultCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
63+
}
49.9 KB
Loading

images/get_mfa_secret_key.png

46.1 KB
Loading
37.8 KB
Loading

images/mfa_setup_correctly.png

16.2 KB
Loading

install.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
if [ ! -x "$(command -v keyfob)" ]; then
55
echo "keyfob is not installed, so I'm going to go grab the mac one for you"
66
wget -O - https://github.com/StevenACoffman/keyfob/releases/download/v0.1.0/keyfob_0.1.0_Darwin_x86_64.tar.gz | tar xzvf
7+
mkdir -p /usr/local/bin
78
mv keyfob /usr/local/bin
89
fi
910

0 commit comments

Comments
 (0)