Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add role description #34

Merged
merged 3 commits into from
Jun 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 40 additions & 31 deletions iamy/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ var cfnResourceRegexp = regexp.MustCompile(`-[A-Z0-9]{10,20}$`)

// AwsFetcher fetches account data from AWS
type AwsFetcher struct {
// As Policy descriptions are immutable, you can skip updating them
// As Policy and Role descriptions are immutable, we can skip fetching them
// when pushing to AWS
SkipFetchingPolicyDescriptions bool
SkipFetchingPolicyAndRoleDescriptions bool

iam *iamClient
s3 *s3Client
account *Account
data AccountData

descriptionFetchWaitGroup sync.WaitGroup
descriptionFetchError error
}

func (a *AwsFetcher) init() error {
Expand Down Expand Up @@ -145,36 +148,35 @@ func (a *AwsFetcher) populateInlinePolicies(source []*iam.PolicyDetail, target *
return nil
}

func (a *AwsFetcher) fetchPolicyDescriptions(resp *iam.GetAccountAuthorizationDetailsOutput) error {
log.Println("Fetching Policy descriptions")
var err error
var wg sync.WaitGroup
for _, policyResp := range resp.Policies {
if cfnResourceRegexp.MatchString(*policyResp.PolicyName) {
continue
}
func (a *AwsFetcher) asyncMarshalPolicyDescriptionIntoStruct(policyArn string, target *string) {
a.descriptionFetchWaitGroup.Add(1)
go func() {
defer a.descriptionFetchWaitGroup.Done()
log.Println("Fetching policy description for", policyArn)

wg.Add(1)
go func(policy *iam.ManagedPolicyDetail) {
defer wg.Done()
desc, fetchErr := a.iam.getPolicyDescription(*policy.Arn)
policy.SetDescription(desc)
if fetchErr != nil {
err = fetchErr
}
}(policyResp)
var err error
*target, err = a.iam.getPolicyDescription(policyArn)
if err != nil {
a.descriptionFetchError = err
}
}()
}

}
wg.Wait()
func (a *AwsFetcher) asyncMarshalRoleDescriptionIntoStruct(roleName string, target *string) {
a.descriptionFetchWaitGroup.Add(1)
go func() {
defer a.descriptionFetchWaitGroup.Done()
log.Println("Fetching role description for", roleName)

return err
var err error
*target, err = a.iam.getRoleDescription(roleName)
if err != nil {
a.descriptionFetchError = err
}
}()
}

func (a *AwsFetcher) populateIamData(resp *iam.GetAccountAuthorizationDetailsOutput) error {
if !a.SkipFetchingPolicyDescriptions {
a.fetchPolicyDescriptions(resp)
}

for _, userResp := range resp.UserDetailList {
if cfnResourceRegexp.MatchString(*userResp.UserName) {
log.Printf("Skipping CloudFormation generated user %s", *userResp.UserName)
Expand Down Expand Up @@ -231,6 +233,10 @@ func (a *AwsFetcher) populateIamData(resp *iam.GetAccountAuthorizationDetailsOut
Path: *roleResp.Path,
}}

if !a.SkipFetchingPolicyAndRoleDescriptions {
a.asyncMarshalRoleDescriptionIntoStruct(*roleResp.RoleName, &role.Description)
}

var err error
role.AssumeRolePolicyDocument, err = NewPolicyDocumentFromEncodedJson(*roleResp.AssumeRolePolicyDocument)
if err != nil {
Expand All @@ -243,7 +249,7 @@ func (a *AwsFetcher) populateIamData(resp *iam.GetAccountAuthorizationDetailsOut
return err
}

a.data.Roles = append(a.data.Roles, role)
a.data.addRole(&role)
}

for _, policyResp := range resp.Policies {
Expand All @@ -268,14 +274,17 @@ func (a *AwsFetcher) populateIamData(resp *iam.GetAccountAuthorizationDetailsOut
nondefaultVersionIds: findNonDefaultPolicyVersionIds(policyResp.PolicyVersionList),
Policy: doc,
}
if policyResp.Description != nil {
p.Description = *policyResp.Description

if !a.SkipFetchingPolicyAndRoleDescriptions {
a.asyncMarshalPolicyDescriptionIntoStruct(*policyResp.Arn, &p.Description)
}

a.data.Policies = append(a.data.Policies, p)
a.data.addPolicy(&p)
}

return nil
a.descriptionFetchWaitGroup.Wait()

return a.descriptionFetchError
}

func findDefaultPolicyVersion(versions []*iam.PolicyVersion) *iam.PolicyVersion {
Expand Down
11 changes: 10 additions & 1 deletion iamy/awsdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,16 @@ func (a *awsSyncCmdGenerator) updateRoles() {

} else {
// Create role
a.cmds.Add("aws", "iam", "create-role", "--role-name", toRole.Name, "--path", path(toRole.Path), "--assume-role-policy-document", toRole.AssumeRolePolicyDocument.JsonString())
args := []string{
"iam", "create-role",
"--role-name", toRole.Name,
"--path", path(toRole.Path),
}
if toRole.Description != "" {
args = append(args, "--description", toRole.Description)
}
args = append(args, "--assume-role-policy-document", toRole.AssumeRolePolicyDocument.JsonString())
a.cmds.Add("aws", args...)

// add new inline policies
for _, ip := range toRole.InlinePolicies {
Expand Down
8 changes: 8 additions & 0 deletions iamy/iam.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ func (c *iamClient) getPolicyDescription(arn string) (string, error) {
return "", err
}

func (c *iamClient) getRoleDescription(name string) (string, error) {
resp, err := c.GetRole(&iam.GetRoleInput{RoleName: &name})
if err == nil && resp.Role.Description != nil {
return *resp.Role.Description, nil
}
return "", err
}

func (c *iamClient) MustGetSecurityCredsForUser(username string) (accessKeyIds, mfaIds []string, hasLoginProfile bool) {
// access keys
listUsersResp, err := c.ListAccessKeys(&iam.ListAccessKeysInput{
Expand Down
17 changes: 9 additions & 8 deletions iamy/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func (p Policy) ResourceType() string {

type Role struct {
iamService `json:"-"`
Description string `json:"Description,omitempty"`
AssumeRolePolicyDocument *PolicyDocument `json:"AssumeRolePolicyDocument"`
InlinePolicies []InlinePolicy `json:"InlinePolicies,omitempty"`
Policies []string `json:"Policies,omitempty"`
Expand Down Expand Up @@ -141,8 +142,8 @@ type AccountData struct {
Account *Account
Users []User
Groups []Group
Roles []Role
Policies []Policy
Roles []*Role
Policies []*Policy
BucketPolicies []BucketPolicy
}

Expand All @@ -151,8 +152,8 @@ func NewAccountData(account string) *AccountData {
Account: NewAccountFromString(account),
Users: []User{},
Groups: []Group{},
Roles: []Role{},
Policies: []Policy{},
Roles: []*Role{},
Policies: []*Policy{},
}
}

Expand All @@ -164,11 +165,11 @@ func (a *AccountData) addGroup(g Group) {
a.Groups = append(a.Groups, g)
}

func (a *AccountData) addRole(r Role) {
func (a *AccountData) addRole(r *Role) {
a.Roles = append(a.Roles, r)
}

func (a *AccountData) addPolicy(p Policy) {
func (a *AccountData) addPolicy(p *Policy) {
a.Policies = append(a.Policies, p)
}

Expand Down Expand Up @@ -199,7 +200,7 @@ func (a *AccountData) FindGroupByName(name, path string) (bool, *Group) {
func (a *AccountData) FindRoleByName(name, path string) (bool, *Role) {
for _, r := range a.Roles {
if r.Name == name && r.Path == path {
return true, &r
return true, r
}
}

Expand All @@ -209,7 +210,7 @@ func (a *AccountData) FindRoleByName(name, path string) (bool, *Role) {
func (a *AccountData) FindPolicyByName(name, path string) (bool, *Policy) {
for _, p := range a.Policies {
if p.Name == name && p.Path == path {
return true, &p
return true, p
}
}

Expand Down
4 changes: 2 additions & 2 deletions iamy/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ func (a *YamlLoadDumper) Load() ([]AccountData, error) {
case "iam/role":
r := Role{iamService: nameAndPath}
err = a.unmarshalYamlFile(fp, &r)
accounts[accountid].addRole(r)
accounts[accountid].addRole(&r)
case "iam/policy":
p := Policy{iamService: nameAndPath}
err = a.unmarshalYamlFile(fp, &p)
accounts[accountid].addPolicy(p)
accounts[accountid].addPolicy(&p)
case "s3":
bp := BucketPolicy{BucketName: name}
err = a.unmarshalYamlFile(fp, &bp)
Expand Down
2 changes: 1 addition & 1 deletion push.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func PushCommand(ui Ui, input PushCommandInput) {
Dir: input.Dir,
}
aws := iamy.AwsFetcher{
SkipFetchingPolicyDescriptions: true,
SkipFetchingPolicyAndRoleDescriptions: true,
}

allDataFromYaml, err := yaml.Load()
Expand Down