Skip to content

Commit 2f69367

Browse files
author
Chris Gilmer
committed
Upgrade aws-vault code and allow for multiple account setup. Rename User to SetupConfig for clarity.
1 parent e83ffcf commit 2f69367

File tree

7 files changed

+221
-238
lines changed

7 files changed

+221
-238
lines changed

cmd/add_profile.go

Lines changed: 20 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func AddProfileInitFlags(flag *pflag.FlagSet) {
2121

2222
flag.String(VaultAWSKeychainNameFlag, VaultAWSKeychainNameDefault, "The aws-vault keychain name")
2323
flag.StringSlice(AWSProfileAccountFlag, []string{}, "A comma separated list of AWS profiles and account IDs 'PROFILE1:ACCOUNTID1,PROFILE2:ACCOUNTID2,...'")
24+
flag.String(AWSBaseProfileFlag, "", fmt.Sprintf("The AWS base profile. If none provided will use first profile name from %q flag", AWSProfileAccountFlag))
2425
flag.String(AWSRegionFlag, endpoints.UsWest2RegionID, "The AWS region")
2526
flag.String(IAMUserFlag, "", "The IAM user name to setup")
2627
flag.String(IAMRoleFlag, "", "The IAM role name assigned to the user being setup")
@@ -43,6 +44,10 @@ func AddProfileCheckConfig(v *viper.Viper) error {
4344
return fmt.Errorf("Region check failed: %w", err)
4445
}
4546

47+
if err := checkProfileAccount(v); err != nil {
48+
return fmt.Errorf("AWS Profile and Account ID check failed: %w", err)
49+
}
50+
4651
if err := checkIAMUser(v); err != nil {
4752
return fmt.Errorf("IAM User check failed: %w", err)
4853
}
@@ -69,42 +74,6 @@ func (sc *SetupConfig) AddProfile() error {
6974
return fmt.Errorf("unable to load aws config file: %w", err)
7075
}
7176

72-
roleProfileSection := iniFile.Section(fmt.Sprintf("profile %s", *sc.RoleProfileName))
73-
74-
// Get the source profile
75-
sourceProfileKey, err := roleProfileSection.GetKey("source_profile")
76-
if err != nil {
77-
return fmt.Errorf("Unable to get source profile from %q: %w", *sc.RoleProfileName, err)
78-
}
79-
sourceProfileName := sourceProfileKey.String()
80-
81-
// Get the MFA Serial
82-
mfaSerialKey, err := roleProfileSection.GetKey("mfa_serial")
83-
if err != nil {
84-
return err
85-
}
86-
mfaSerial := mfaSerialKey.String()
87-
88-
for _, element := range sc.NewProfiles {
89-
profileName := strings.Split(element, ":")[0]
90-
awsAccountID := strings.Split(element, ":")[1]
91-
92-
profile := vault.ProfileSection{
93-
Name: profileName,
94-
RoleARN: fmt.Sprintf("arn:%s:iam::%s:role/%s",
95-
sc.Partition,
96-
awsAccountID,
97-
sc.Role),
98-
MfaSerial: mfaSerial,
99-
Region: sc.Region,
100-
}
101-
102-
// Add the role profile with base as the source profile
103-
if err := sc.UpdateAWSProfile(iniFile, &profile, &sourceProfileName); err != nil {
104-
return err
105-
}
106-
}
107-
10877
// save it back to the aws config path
10978
return iniFile.SaveTo(sc.Config.Path)
11079
}
@@ -154,7 +123,7 @@ func addProfileFunction(cmd *cobra.Command, args []string) error {
154123
// Get command line flag values
155124
awsRegion := v.GetString(AWSRegionFlag)
156125
awsVaultKeychainName := v.GetString(VaultAWSKeychainNameFlag)
157-
awsVaultProfileAccount := v.GetStringSlice(AWSProfileAccountFlag)
126+
// awsProfileAccount := v.GetStringSlice(AWSProfileAccountFlag)
158127
iamUser := v.GetString(IAMUserFlag)
159128
iamRole := v.GetString(IAMRoleFlag)
160129
output := v.GetString(OutputFlag)
@@ -179,16 +148,20 @@ func addProfileFunction(cmd *cobra.Command, args []string) error {
179148
}
180149

181150
setupConfig := SetupConfig{
182-
Logger: logger,
183-
Name: iamUser,
184-
Role: iamRole,
185-
Region: awsRegion,
186-
Partition: partition,
187-
RoleProfileName: &awsVaultProfileAccount[0],
188-
NewProfiles: awsVaultProfileAccount[1:],
189-
Output: output,
190-
Config: config,
191-
Keyring: keyring,
151+
// Config
152+
Logger: logger,
153+
Config: config,
154+
Keyring: keyring,
155+
156+
// Profile Inputs
157+
IAMUser: iamUser,
158+
IAMRole: iamRole,
159+
Region: awsRegion,
160+
Partition: partition,
161+
Output: output,
162+
163+
// RoleProfileName: &awsVaultProfileAccount[0],
164+
// NewProfiles: awsVaultProfileAccount[1:],
192165
}
193166

194167
if err := setupConfig.AddProfile(); err != nil {

cmd/cli.go

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,18 @@ import (
1212
const (
1313
// AWSRegionFlag is the generic AWS Region Flag
1414
AWSRegionFlag string = "aws-region"
15-
// AWSAccountIDFlag is the AWS AccountID Flag
16-
AWSAccountIDFlag string = "aws-account-id"
1715

1816
// VaultAWSKeychainNameFlag is the aws-vault keychain name Flag
1917
VaultAWSKeychainNameFlag string = "aws-vault-keychain-name"
2018
// VaultAWSKeychainNameDefault is the aws-vault default keychain name
2119
VaultAWSKeychainNameDefault string = "login"
22-
// VaultAWSProfileFlag is the aws-vault profile name Flag
23-
VaultAWSProfileFlag string = "aws-profile"
2420

2521
// AWSProfileAccountFlag is the combined AWS profile name and account ID Flag
2622
AWSProfileAccountFlag string = "aws-profile-account"
27-
//// AWSBaseProfileFlag is the AWS base profile name Flag
28-
//AWSBaseProfileFlag string = "aws-base-profile"
23+
// AWSBaseProfileFlag is the AWS base profile name Flag
24+
AWSBaseProfileFlag string = "aws-base-profile"
25+
// AWSProfileFlag is the AWS Profile flag
26+
AWSProfileFlag string = "aws-profile"
2927

3028
// IAMUserFlag is the IAM User name Flag
3129
IAMUserFlag string = "iam-user"
@@ -59,14 +57,6 @@ func (e *errInvalidKeychainName) Error() string {
5957
return fmt.Sprintf("invalid keychain name '%s'", e.KeychainName)
6058
}
6159

62-
// type errInvalidAWSProfile struct {
63-
// Profile string
64-
// }
65-
//
66-
// func (e *errInvalidAWSProfile) Error() string {
67-
// return fmt.Sprintf("invalid aws profile '%s'", e.Profile)
68-
// }
69-
7060
func checkVault(v *viper.Viper) error {
7161
// Both keychain name and profile are required or both must be missing
7262
keychainName := v.GetString(VaultAWSKeychainNameFlag)
@@ -77,11 +67,6 @@ func checkVault(v *viper.Viper) error {
7767
return fmt.Errorf("%s is invalid, expected %v: %w", VaultAWSKeychainNameFlag, keychainNames, &errInvalidKeychainName{KeychainName: keychainName})
7868
}
7969

80-
// awsProfile := v.GetString(VaultAWSProfileFlag)
81-
// if len(awsProfile) == 0 {
82-
// return fmt.Errorf("%s must not be empty: %w", VaultAWSProfileFlag, &errInvalidAWSProfile{Profile: awsProfile})
83-
// }
84-
8570
return nil
8671
}
8772

@@ -114,7 +99,7 @@ func (e *errInvalidAccountID) Error() string {
11499

115100
func checkAccountID(id string) error {
116101
if matched, err := regexp.Match(`^\d{12}$`, []byte(id)); !matched || err != nil {
117-
return fmt.Errorf("%s must be a 12 digit number: %w", AWSAccountIDFlag, &errInvalidAccountID{AccountID: id})
102+
return fmt.Errorf("AWS Account ID must be a 12 digit number: %w", &errInvalidAccountID{AccountID: id})
118103
}
119104

120105
return nil

cmd/cli_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ func (suite *cliTestSuite) TestCheckVault() {
6161
}
6262
for _, testValue := range testValues {
6363
suite.viper.Set(VaultAWSKeychainNameFlag, testValue)
64-
suite.viper.Set(VaultAWSProfileFlag, "profile")
64+
suite.viper.Set(AWSProfileFlag, "profile")
6565
suite.NoError(checkVault(suite.viper))
6666
}
6767
testValuesWithErrors := []string{
6868
"AnyOtherKeychainName",
6969
}
7070
for _, testValue := range testValuesWithErrors {
7171
suite.viper.Set(VaultAWSKeychainNameFlag, testValue)
72-
suite.viper.Set(VaultAWSProfileFlag, "profile")
72+
suite.viper.Set(AWSProfileFlag, "profile")
7373
suite.Error(checkVault(suite.viper))
7474
}
7575
}

cmd/main_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"log"
7+
"os"
8+
"strings"
9+
"testing"
10+
11+
"github.com/spf13/pflag"
12+
"github.com/spf13/viper"
13+
"github.com/stretchr/testify/suite"
14+
)
15+
16+
type commandTestSuite struct {
17+
suite.Suite
18+
viper *viper.Viper
19+
logger *log.Logger
20+
}
21+
22+
type initFlags func(f *pflag.FlagSet)
23+
24+
func (suite *commandTestSuite) Setup(fn initFlags, flagSet []string) {
25+
// Disable any logging that isn't attached to the logger unless using the verbose flag
26+
log.SetOutput(ioutil.Discard)
27+
log.SetFlags(0)
28+
29+
// Setup logger
30+
var logger = log.New(os.Stdout, "", log.LstdFlags)
31+
32+
// Remove the flags for the logger
33+
logger.SetFlags(0)
34+
suite.SetLogger(logger)
35+
36+
// Setup viper
37+
suite.viper = nil
38+
39+
flag := pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
40+
fn(flag)
41+
errFlagParse := flag.Parse(flagSet)
42+
if errFlagParse != nil {
43+
suite.logger.Fatal(errFlagParse)
44+
}
45+
46+
v := viper.New()
47+
err := v.BindPFlags(flag)
48+
if err != nil {
49+
suite.logger.Fatal(fmt.Errorf("could not bind flags: %w", err))
50+
}
51+
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
52+
v.AutomaticEnv()
53+
54+
suite.SetViper(v)
55+
}
56+
57+
func (suite *commandTestSuite) SetViper(v *viper.Viper) {
58+
suite.viper = v
59+
}
60+
61+
func (suite *commandTestSuite) SetLogger(logger *log.Logger) {
62+
suite.logger = logger
63+
}
64+
65+
func TestCommandSuite(t *testing.T) {
66+
suite.Run(t, &commandTestSuite{})
67+
}
68+
69+
func (suite *commandTestSuite) TestAddProfileFlags() {
70+
suite.Setup(AddProfileInitFlags, []string{
71+
"--aws-profile-account", "test-new:012345678901",
72+
"--iam-user", "me",
73+
"--iam-role", "engineer",
74+
})
75+
suite.NoError(AddProfileCheckConfig(suite.viper))
76+
}
77+
78+
func (suite *commandTestSuite) TestSetupFlags() {
79+
suite.Setup(SetupUserInitFlags, []string{
80+
"--aws-profile-account", "test-id:012345678901",
81+
"--iam-user", "me",
82+
"--iam-role", "engineer",
83+
})
84+
suite.NoError(SetupUserCheckConfig(suite.viper))
85+
}

0 commit comments

Comments
 (0)