diff --git a/go.mod b/go.mod index 10ca8843..896d919c 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.14 require ( github.com/AlecAivazis/survey/v2 v2.0.7 - github.com/aws/aws-sdk-go v1.32.6 + github.com/aws/aws-sdk-go v1.32.8 github.com/blang/semver v3.5.1+incompatible github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 // indirect github.com/chanzuckerberg/go-misc v0.0.0-20200622164707-c19d1f2e9ea7 @@ -25,7 +25,8 @@ require ( github.com/spf13/cobra v1.0.0 github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.5.1 - golang.org/x/sys v0.0.0-20200620081246-981b61492c35 // indirect + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect + golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 // indirect golang.org/x/text v0.3.3 // indirect gopkg.in/ini.v1 v1.57.0 ) diff --git a/go.sum b/go.sum index 8a7d277f..eb11307f 100644 --- a/go.sum +++ b/go.sum @@ -11,12 +11,9 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/aws/aws-lambda-go v1.17.0/go.mod h1:FEwgPLE6+8wcGBTe5cJN3JWurd1Ztm9zN4jsXsjzKKw= -github.com/aws/aws-sdk-go v1.32.3 h1:E3OciOGVlJrv1gQ2T7/Oou+I9nGPB2j978THQjvZBf0= github.com/aws/aws-sdk-go v1.32.3/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.32.4 h1:J2OMvipVB5dPIn+VH7L5rOqM4WoTsBxOqv+I06sjYOM= -github.com/aws/aws-sdk-go v1.32.4/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.32.6 h1:HoswAabUWgnrUF7X/9dr4WRgrr8DyscxXvTDm7Qw/5c= -github.com/aws/aws-sdk-go v1.32.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.32.8 h1:ULxiQqR1eZ+k2/1gqv3GYAjkunlS7ncVU2eL801t08M= +github.com/aws/aws-sdk-go v1.32.8/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -27,20 +24,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894 h1:JLaf/iINcLyjwbtTsCJjc6rtlASgHeIJPrB6QmwURnA= github.com/certifi/gocertifi v0.0.0-20200211180108-c7c1fbc02894/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/chanzuckerberg/go-misc v0.0.0-20200617191514-c995aa16b6e6 h1:K6IJHAWKTKZ3vMmC996MG6ClTzVgBnLG3o/lHJzLp5k= -github.com/chanzuckerberg/go-misc v0.0.0-20200617191514-c995aa16b6e6/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= -github.com/chanzuckerberg/go-misc v0.0.0-20200622144829-5993a83bbc54 h1:jk84xmehtXMqSvGeLHd+l/LEHyl06nCG6GHwV6pFxx0= -github.com/chanzuckerberg/go-misc v0.0.0-20200622144829-5993a83bbc54/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= -github.com/chanzuckerberg/go-misc v0.0.0-20200622145258-05520914050b h1:1lUu/TiXSnkzvrVFrc1wnYlJhHyDvFXVw6WZBuPkPvQ= -github.com/chanzuckerberg/go-misc v0.0.0-20200622145258-05520914050b/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= -github.com/chanzuckerberg/go-misc v0.0.0-20200622150000-9c83d91c9956 h1:9j5NKbBTTeFkjdY8VQexi803VUrcW1FS/aJeOxuMu78= -github.com/chanzuckerberg/go-misc v0.0.0-20200622150000-9c83d91c9956/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= -github.com/chanzuckerberg/go-misc v0.0.0-20200622154142-f42f2c75dea0 h1:mNMIGygFuh9i+yndecyOr2sMvcj5qtZChBC9rxYjtCc= -github.com/chanzuckerberg/go-misc v0.0.0-20200622154142-f42f2c75dea0/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= -github.com/chanzuckerberg/go-misc v0.0.0-20200622154257-dbbfc6c61490 h1:AGDT6UcVZm8ws0VXlh5+1V4C82t4PcVV9D6TxHhUK/Y= -github.com/chanzuckerberg/go-misc v0.0.0-20200622154257-dbbfc6c61490/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= -github.com/chanzuckerberg/go-misc v0.0.0-20200622155349-3d759d27d00c h1:ETFNvnLUeQLG3vFohB0xF64usARjFIx1UavU/GalahA= -github.com/chanzuckerberg/go-misc v0.0.0-20200622155349-3d759d27d00c/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= github.com/chanzuckerberg/go-misc v0.0.0-20200622164707-c19d1f2e9ea7 h1:Jjh7iueHmSLDImsI5VqAiDjvl7/209+6X2hK3BP09K0= github.com/chanzuckerberg/go-misc v0.0.0-20200622164707-c19d1f2e9ea7/go.mod h1:DvXIQAf/+jobYeXCxrg7NZibYv8ek7KbvFXO0V44fHY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -103,7 +86,6 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= @@ -194,7 +176,6 @@ github.com/okta/okta-sdk-golang/v2 v2.0.0 h1:qwl5Ezpy5a3I2WphiHolpgTtOC+YMTDIpFq github.com/okta/okta-sdk-golang/v2 v2.0.0/go.mod h1:fQubbeV8gksr8e1pmRVSE8kIj1TFqlgYqi8WsvSKmQk= github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627 h1:pSCLCl6joCFRnjpeojzOpEYs4q7Vditq8fySFG5ap3Y= github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/patrickmn/go-cache v1.0.0 h1:3gD5McaYs9CxjyK5AXGcq8gdeCARtd/9gJDUvVeaZ0Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterhellberg/link v1.1.0 h1:s2+RH8EGuI/mI4QwrWGSYQCRz7uNgip9BaM04HKu5kc= github.com/peterhellberg/link v1.1.0/go.mod h1:gtSlOT4jmkY8P47hbTc8PTgiDDWpdPbFYl75keYyBB8= @@ -234,7 +215,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -272,6 +252,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -315,13 +297,11 @@ golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200620081246-981b61492c35 h1:wb/9mP8eUAmHfkM8RmpeLq6nUA7c2i5+bQOtcDftjaE= -golang.org/x/sys v0.0.0-20200620081246-981b61492c35/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -357,7 +337,6 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= diff --git a/pkg/aws_config_client/completer.go b/pkg/aws_config_client/completer.go index d0a89864..162bab82 100644 --- a/pkg/aws_config_client/completer.go +++ b/pkg/aws_config_client/completer.go @@ -65,7 +65,11 @@ func (c *completer) awsProfileNameValidator(input interface{}) error { func (c *completer) calculateDefaultProfileName(account server.AWSAccount) string { invalid := regexp.MustCompile("[^a-zA-Z0-9_-]") - replaced := invalid.ReplaceAllString(account.Name, "-") + accountName := account.Alias + if accountName == "" { + accountName = account.Name + } + replaced := invalid.ReplaceAllString(accountName, "-") return strings.ToLower(replaced) } diff --git a/pkg/aws_config_client/completer_test.go b/pkg/aws_config_client/completer_test.go index a859ac61..d751e952 100644 --- a/pkg/aws_config_client/completer_test.go +++ b/pkg/aws_config_client/completer_test.go @@ -166,6 +166,40 @@ func TestAWSProfileNameValidator(t *testing.T) { } } +func TestCalCulateDefaultProfileName(t *testing.T) { + type test struct { + input server.AWSAccount + output string + } + + tests := []test{ + { + input: server.AWSAccount{ + Name: "test1", + ID: "test_id_1", + Alias: "", + }, + output: "test1", + }, + { + input: server.AWSAccount{ + Name: "test2", + ID: "test_id_2", + Alias: "alias2", + }, + output: "alias2", + }, + } + + r := require.New(t) + + c := NewCompleter(nil, generateDummyData()) + for _, test := range tests { + profleName := c.calculateDefaultProfileName(test.input) + r.Equal(test.output, profleName) + } +} + func generateDummyData() *server.AWSConfig { return &server.AWSConfig{ Profiles: []server.AWSProfile{ @@ -174,6 +208,7 @@ func generateDummyData() *server.AWSConfig { AWSAccount: server.AWSAccount{ Name: "test1", ID: "test_id_1", + Alias: "test1", }, RoleARN: "test1RoleName", IssuerURL: "issuer-url", @@ -184,6 +219,7 @@ func generateDummyData() *server.AWSConfig { AWSAccount: server.AWSAccount{ Name: "test1", ID: "test_id_1", + Alias: "test1", }, RoleARN: "test2RoleName", IssuerURL: "issuer-url", @@ -194,6 +230,7 @@ func generateDummyData() *server.AWSConfig { AWSAccount: server.AWSAccount{ Name: "Account Name With Spaces", ID: "account id 2", + Alias: "Account Name With Spaces", }, RoleARN: "test1RoleName", IssuerURL: "issuer-url", @@ -204,6 +241,7 @@ func generateDummyData() *server.AWSConfig { AWSAccount: server.AWSAccount{ Name: "Account Name With Spaces", ID: "account id 2", + Alias: "Account Name With Spaces", }, RoleARN: "test1RoleName", IssuerURL: "issuer-url", diff --git a/pkg/aws_config_server/assemble_config.go b/pkg/aws_config_server/assemble_config.go index a230de8f..d9d459d7 100644 --- a/pkg/aws_config_server/assemble_config.go +++ b/pkg/aws_config_server/assemble_config.go @@ -21,7 +21,7 @@ type ClientIDToAWSRoles struct { awsClient *cziAWS.Client } -func (a *ClientIDToAWSRoles) getRoles(ctx context.Context, masterRoles []string, workerRole string) error { +func (a *ClientIDToAWSRoles) getWorkerRoles(ctx context.Context, masterRoles []string, workerRole string) error { for _, role_arn := range masterRoles { masterAWSConfig := &aws.Config{ Credentials: stscreds.NewCredentials(a.awsSession, role_arn), @@ -46,7 +46,7 @@ func (a *ClientIDToAWSRoles) getRoles(ctx context.Context, masterRoles []string, return nil } -func (a *ClientIDToAWSRoles) mapRoles( +func (a *ClientIDToAWSRoles) fetchAssumableRoles( ctx context.Context, oidcProvider string, ) error { @@ -55,13 +55,19 @@ func (a *ClientIDToAWSRoles) mapRoles( Credentials: stscreds.NewCredentials(a.awsSession, roleARN.String()), CredentialsChainVerboseErrors: aws.Bool(true), } + iamClient := a.awsClient.WithIAM(workerAWSConfig).IAM.Svc workerRoles, err := listRoles(ctx, iamClient) if err != nil { return errors.Wrapf(err, "%s error", accountName) } - - err = clientRoleMapFromProfile(ctx, accountName, workerRoles, oidcProvider, a.clientRoleMapping) + // account aliases will be used to determine profile names + // by the completer in cli + accountAlias, err := getAcctAlias(ctx, iamClient) + if err != nil { + return errors.Wrapf(err, "%s error", accountName) + } + err = clientRoleMapFromProfile(ctx, accountName, accountAlias, workerRoles, oidcProvider, a.clientRoleMapping) if err != nil { return errors.Wrap(err, "Unable to complete mapping between ClientIDs and ConfigProfiles") } @@ -89,11 +95,13 @@ func createAWSConfig( RoleARN: config.RoleARN.String(), AWSAccount: AWSAccount{ Name: config.AcctName, + Alias: config.AcctAlias, ID: config.RoleARN.AccountID, }, IssuerURL: configParams.OIDCProvider, RoleName: config.RoleName, } + awsConfig.Profiles = append(awsConfig.Profiles, profile) } } diff --git a/pkg/aws_config_server/cache.go b/pkg/aws_config_server/cache.go index 2f6facac..8599e2ba 100644 --- a/pkg/aws_config_server/cache.go +++ b/pkg/aws_config_server/cache.go @@ -70,11 +70,11 @@ func (c *CachedGetClientIDToProfiles) refresh( roleARNs: map[string]arn.ARN{}, awsClient: cziAWS.New(awsSession), } - err := configData.getRoles(ctx, configParams.AWSMasterRoles, configParams.AWSWorkerRole) + err := configData.getWorkerRoles(ctx, configParams.AWSMasterRoles, configParams.AWSWorkerRole) if err != nil { return errors.Wrap(err, "Unable to get list of RoleARNs accessible by the Master Roles") } - err = configData.mapRoles(ctx, configParams.OIDCProvider) + err = configData.fetchAssumableRoles(ctx, configParams.OIDCProvider) if err != nil { return errors.Wrap(err, "Unable to create mapping needed for config generation") } diff --git a/pkg/aws_config_server/custom_actions_policy_test.go b/pkg/aws_config_server/custom_actions_policy_test.go index a068cbd6..fca1a2cc 100644 --- a/pkg/aws_config_server/custom_actions_policy_test.go +++ b/pkg/aws_config_server/custom_actions_policy_test.go @@ -44,7 +44,7 @@ func TestMultipleActions(t *testing.T) { r.Len(iamOutput, 1) clientRoleMap := make(map[okta.ClientID][]ConfigProfile) - err = clientRoleMapFromProfile(ctx, "accountName", testRoles3, oidcProvider, clientRoleMap) + err = clientRoleMapFromProfile(ctx, "accountName", "accountAlias", testRoles3, oidcProvider, clientRoleMap) r.NoError(err) // Nothing weird happened r.NotEmpty(clientRoleMap) // There are valid clientIDs r.Contains(clientRoleMap, okta.ClientID("clientIDValue3")) // Only the valid ID is present diff --git a/pkg/aws_config_server/list_roles.go b/pkg/aws_config_server/list_roles.go index 027d7e5c..80f53917 100644 --- a/pkg/aws_config_server/list_roles.go +++ b/pkg/aws_config_server/list_roles.go @@ -42,9 +42,10 @@ type Principal struct { } type ConfigProfile struct { - AcctName string - RoleARN arn.ARN - RoleName string + AcctName string + AcctAlias string + RoleARN arn.ARN + RoleName string } // We can skip over roles with specific tags @@ -117,6 +118,7 @@ func (s *Action) UnmarshalJSON(data []byte) error { func clientRoleMapFromProfile( ctx context.Context, acctName string, + acctAlias string, roles []*iam.Role, oidcProvider string, clientRoleMapping map[okta.ClientID][]ConfigProfile) error { @@ -174,9 +176,10 @@ func clientRoleMapFromProfile( } currentConfig := ConfigProfile{ - AcctName: acctName, - RoleARN: roleARN, - RoleName: *role.RoleName, + AcctName: acctName, + AcctAlias: acctAlias, + RoleARN: roleARN, + RoleName: *role.RoleName, } if _, ok := clientRoleMapping[clientID]; !ok { @@ -219,3 +222,22 @@ func GetActiveAccountList( return activeAccounts, nil } + +func getAcctAlias(ctx context.Context, svc iamiface.IAMAPI) (string, error) { + input := &iam.ListAccountAliasesInput{} + output, err := svc.ListAccountAliases(input) + + if err != nil { + if awsErr, ok := err.(awserr.Error); ok && (awsErr.Code() == ignoreAWSError) { + logrus.WithError(err).Error("Unable to get aliases for this account") + return "", nil + } + return "", errors.Wrap(err, "Error getting account alias") + } + + // no alias + if output == nil || len(output.AccountAliases) == 0 { + return "", nil + } + return *output.AccountAliases[0], nil +} diff --git a/pkg/aws_config_server/list_roles_test.go b/pkg/aws_config_server/list_roles_test.go index a44b5d8f..a5478606 100644 --- a/pkg/aws_config_server/list_roles_test.go +++ b/pkg/aws_config_server/list_roles_test.go @@ -62,7 +62,7 @@ func TestClientRoleMapFromProfile(t *testing.T) { testRoles1[0].AssumeRolePolicyDocument = &newPolicyStr clientRoleMap := map[okta.ClientID][]ConfigProfile{} - err = clientRoleMapFromProfile(ctx, "accountName", testRoles1, oidcProvider, clientRoleMap) + err = clientRoleMapFromProfile(ctx, "accountName", "accountAlias", testRoles1, oidcProvider, clientRoleMap) r.NoError(err) // Nothing weird happened r.NotEmpty(clientRoleMap) // There are valid clientIDs r.Contains(clientRoleMap, okta.ClientID("clientIDValue1")) // Only the valid ID is present @@ -79,7 +79,7 @@ func TestClientRoleMapFromProfile(t *testing.T) { newPolicyStr = url.PathEscape(string(newPolicyData)) testRoles2[0].AssumeRolePolicyDocument = &newPolicyStr - err = clientRoleMapFromProfile(ctx, "accountName2", testRoles2, oidcProvider, clientRoleMap) + err = clientRoleMapFromProfile(ctx, "accountName2", "accountAlias2", testRoles2, oidcProvider, clientRoleMap) r.NoError(err) r.Len(clientRoleMap[okta.ClientID("clientIDValue1")], 2) // original ClientID has another entry @@ -92,7 +92,7 @@ func TestNoPolicyDocument(t *testing.T) { r := require.New(t) clientRoleMap := map[okta.ClientID][]ConfigProfile{} - err := clientRoleMapFromProfile(ctx, "accountName", testRoles0, oidcProvider, clientRoleMap) + err := clientRoleMapFromProfile(ctx, "accountName", "accountAlias", testRoles0, oidcProvider, clientRoleMap) r.NoError(err) r.Empty(clientRoleMap) } @@ -135,3 +135,41 @@ func TestGetActiveAccountList(t *testing.T) { r.Len(acctList, 1) r.Equal(*acctList[0].Name, "Account1") // the active account } + +func TestGetAcctAlias(t *testing.T) { + ctx := context.Background() + r := require.New(t) + ctrl := gomock.NewController(t) + + client := &cziAWS.Client{} + _, mock := client.WithMockIAM(ctrl) + + testAlias := "account_alias_1" + + mock.EXPECT(). + ListAccountAliases(gomock.Any()).Return( + &iam.ListAccountAliasesOutput{AccountAliases: []*string{&testAlias}}, nil, + ) + + outputString, err := getAcctAlias(ctx, mock) + r.NoError(err) + r.Equal(testAlias, outputString) +} + +func TestGetAcctAliasNoAlias(t *testing.T) { + ctx := context.Background() + r := require.New(t) + ctrl := gomock.NewController(t) + + client := &cziAWS.Client{} + _, mock := client.WithMockIAM(ctrl) + + mock.EXPECT(). + ListAccountAliases(gomock.Any()).Return( + &iam.ListAccountAliasesOutput{AccountAliases: []*string{}}, nil, + ) + + outputString, err := getAcctAlias(ctx, mock) + r.NoError(err) + r.Equal("", outputString) +} diff --git a/pkg/aws_config_server/types.go b/pkg/aws_config_server/types.go index e00a6441..6d1eafe2 100644 --- a/pkg/aws_config_server/types.go +++ b/pkg/aws_config_server/types.go @@ -77,4 +77,5 @@ type AWSProfile struct { type AWSAccount struct { ID string `json:"id,omitempty"` Name string `json:"name,omitempty"` + Alias string `json:"alias,omitempty"` }