diff --git a/iamy/aws.go b/iamy/aws.go index 79ccdfb..9f5e3c1 100644 --- a/iamy/aws.go +++ b/iamy/aws.go @@ -22,7 +22,7 @@ type AwsFetcher struct { Debug *log.Logger - iam *iamClient + iam iamClientiface s3 *s3Client account *Account data AccountData @@ -120,8 +120,11 @@ func (a *AwsFetcher) fetchIamData() error { }), }, func(resp *iam.GetAccountAuthorizationDetailsOutput, lastPage bool) bool { + // There's a bug here. This doesn't set the variable outside this function scope + // So IAMY just swallows any errors returned from populateIamData() populateIamDataErr = a.populateIamData(resp) if populateIamDataErr != nil { + log.Println("Error Fetching IAM Data", populateIamDataErr) return false } return true diff --git a/iamy/aws_test.go b/iamy/aws_test.go index 62e27c2..aff5cbe 100644 --- a/iamy/aws_test.go +++ b/iamy/aws_test.go @@ -2,6 +2,10 @@ package iamy import ( "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/iam" ) func TestIsSkippableManagedResource(t *testing.T) { @@ -45,3 +49,56 @@ func TestIsSkippableManagedResource(t *testing.T) { }) } } + +type mockIam struct { + iamClientiface + policyDocument string +} + +func (m *mockIam) GetAccountAuthorizationDetailsPages(input *iam.GetAccountAuthorizationDetailsInput, fn func(*iam.GetAccountAuthorizationDetailsOutput, bool) bool) error { + now := time.Now() + fn(&iam.GetAccountAuthorizationDetailsOutput{ + Policies: []*iam.ManagedPolicyDetail{ + { + Arn: aws.String("arn:aws:iam::aws:policy/IAMReadOnlyAccess"), + AttachmentCount: aws.Int64(0), + CreateDate: &now, + DefaultVersionId: aws.String("v4"), + Description: aws.String("Provides read only access to IAM via the AWS Management Console."), + IsAttachable: aws.Bool(true), + Path: aws.String("/"), + PermissionsBoundaryUsageCount: aws.Int64(0), + PolicyId: aws.String("ANPAJKSO7NDY4T57MWDSQ"), + PolicyName: aws.String("IAMReadOnlyAccess"), + PolicyVersionList: []*iam.PolicyVersion{ + { + CreateDate: &now, + Document: &m.policyDocument, + IsDefaultVersion: aws.Bool(true), + VersionId: aws.String("v4"), + }, + }, + UpdateDate: &now, + }, + }, + }, true) + return nil +} + +func (m *mockIam) ListInstanceProfilesPages(*iam.ListInstanceProfilesInput, func(*iam.ListInstanceProfilesOutput, bool) bool) error { + return nil +} +func TestFetchIamData(t *testing.T) { + mockIamClient := &mockIam{ + policyDocument: "InvalidPolicy%zz}}", + } + + fetcher := AwsFetcher{ + SkipFetchingPolicyAndRoleDescriptions: true, + iam: mockIamClient, + } + err := fetcher.fetchIamData() + if err == nil { + t.Error("We expected fetch IAM to fail because the policy document was invalid. But it didn't") + } +} diff --git a/iamy/iam.go b/iamy/iam.go index d6489ee..ef82f99 100644 --- a/iamy/iam.go +++ b/iamy/iam.go @@ -7,6 +7,13 @@ import ( "github.com/aws/aws-sdk-go/service/iam/iamiface" ) +type iamClientiface interface { + iamiface.IAMAPI + getPolicyDescription(string) (string, error) + getRoleDescription(string) (string, error) + MustGetSecurityCredsForUser(string) ([]string, []string, bool) +} + type iamClient struct { iamiface.IAMAPI }