Skip to content

Commit f7d009b

Browse files
authored
Update IsAdmin check to iterate through policies attached to roles (#1920)
1 parent 66c9545 commit f7d009b

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

cli/cmd/lib_aws_creds.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func warnIfNotAdmin(awsClient *aws.Client) {
7272
}
7373

7474
if !awsClient.IsAdmin() {
75-
fmt.Println(fmt.Sprintf("warning: your IAM user%s does not have administrator access. This may prevent this command from executing correctly, so it is recommended to attach the AdministratorAccess policy to your IAM user.", accessKeyMsg), "", "")
75+
fmt.Println(fmt.Sprintf("warning: your IAM user or assumed role%s does not have administrator access. This may prevent this command from executing correctly, so it is recommended to attach the AdministratorAccess policy to your IAM user or role.", accessKeyMsg), "", "")
7676
}
7777
}
7878

pkg/lib/aws/iam.go

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ import (
2020
"strings"
2121

2222
"github.com/aws/aws-sdk-go/aws"
23+
"github.com/aws/aws-sdk-go/aws/awserr"
2324
"github.com/aws/aws-sdk-go/service/iam"
2425
"github.com/cortexlabs/cortex/pkg/lib/errors"
2526
)
2627

28+
const _administratorAccessARN = "arn:aws:iam::aws:policy/AdministratorAccess"
29+
2730
func (c *Client) GetUser() (iam.User, error) {
2831
getUserOutput, err := c.IAM().GetUser(nil)
2932
if err != nil {
@@ -87,12 +90,7 @@ func (c *Client) GetManagedPoliciesForUser(userName string) ([]iam.AttachedPolic
8790
return policies, nil
8891
}
8992

90-
func (c *Client) IsAdmin() bool {
91-
user, err := c.GetUser()
92-
if err != nil {
93-
return false
94-
}
95-
93+
func (c *Client) isAdminUser(user iam.User) bool {
9694
// Root users may not have a user name
9795
if user.UserName == nil {
9896
return true
@@ -109,14 +107,69 @@ func (c *Client) IsAdmin() bool {
109107
}
110108

111109
for _, policy := range policies {
112-
if *policy.PolicyArn == "arn:aws:iam::aws:policy/AdministratorAccess" {
110+
if *policy.PolicyArn == _administratorAccessARN {
113111
return true
114112
}
115113
}
116114

117115
return false
118116
}
119117

118+
func (c *Client) isRoleAdmin() bool {
119+
identity, err := c.STS().GetCallerIdentity(nil)
120+
if err != nil {
121+
return false
122+
}
123+
124+
arn := identity.Arn
125+
if arn == nil {
126+
return false
127+
}
128+
129+
if !strings.Contains(*arn, ":assumed-role/") {
130+
return false
131+
}
132+
133+
// expected to be in form arn:aws:sts::account-id:assumed-role/role-name/role-session-name
134+
arnSplit := strings.Split(*arn, "/")
135+
if len(arnSplit) < 2 {
136+
return false
137+
}
138+
roleName := arnSplit[1]
139+
140+
isAdmin := false
141+
c.IAM().ListAttachedRolePoliciesPages(&iam.ListAttachedRolePoliciesInput{
142+
RoleName: &roleName,
143+
}, func(policies *iam.ListAttachedRolePoliciesOutput, lastPage bool) bool {
144+
for _, policy := range policies.AttachedPolicies {
145+
if *policy.PolicyArn == _administratorAccessARN {
146+
isAdmin = true
147+
return false
148+
}
149+
}
150+
151+
return !lastPage
152+
})
153+
return isAdmin
154+
}
155+
156+
func (c *Client) IsAdmin() bool {
157+
user, err := c.GetUser()
158+
if err != nil {
159+
awsErr, ok := errors.CauseOrSelf(err).(awserr.Error)
160+
if !ok {
161+
return false
162+
}
163+
164+
// this particular error is returned if GetUser() is invoked using credentials that are not for users
165+
if awsErr.Code() == "ValidationError" && strings.Contains(strings.ToLower(err.Error()), strings.ToLower("calling with non-User credentials")) {
166+
return c.isRoleAdmin()
167+
}
168+
return false
169+
}
170+
return c.isAdminUser(user)
171+
}
172+
120173
// delete non default policy versions and then delete the policy (as required by aws)
121174
func (c *Client) DeletePolicy(policyARN string) error {
122175
policyVersionList, err := c.IAM().ListPolicyVersions(&iam.ListPolicyVersionsInput{

0 commit comments

Comments
 (0)