diff --git a/pkg/connector/account.go b/pkg/connector/account.go index f4aca4cd..b843e1c8 100644 --- a/pkg/connector/account.go +++ b/pkg/connector/account.go @@ -249,7 +249,7 @@ func (o *accountResourceType) Entitlements(ctx context.Context, resource *v2.Res annos.Update(&v2.V1Identifier{ Id: b.String(), }) - displayName := fmt.Sprintf("%s Permission Set", awsSdk.ToString(ps.Name)) + displayName := fmt.Sprintf("%s - %s Permission Set", resource.DisplayName, awsSdk.ToString(ps.Name)) member := entitlementSdk.NewAssignmentEntitlement(resource, displayName, entitlementSdk.WithGrantableTo(resourceTypeSSOUser, resourceTypeSSOGroup), ) @@ -913,6 +913,7 @@ func accountProfile(_ context.Context, account types.Account) map[string]interfa profile := make(map[string]interface{}) profile["aws_account_arn"] = awsSdk.ToString(account.Arn) profile["aws_account_id"] = awsSdk.ToString(account.Id) + profile["aws_account_name"] = awsSdk.ToString(account.Name) return profile } diff --git a/pkg/connector/connector.go b/pkg/connector/connector.go index bfe75971..55ecccc9 100644 --- a/pkg/connector/connector.go +++ b/pkg/connector/connector.go @@ -429,7 +429,7 @@ func (c *AWS) SetupClients(ctx context.Context) error { func (c *AWS) ResourceSyncers(ctx context.Context) []connectorbuilder.ResourceSyncerV2 { l := ctxzap.Extract(ctx) rs := []connectorbuilder.ResourceSyncerV2{ - iamUserBuilder(c.iamClient, c.awsClientFactory), + iamUserBuilder(c.iamClient, c.awsClientFactory, c.orgClient), iamRoleBuilder(c.iamClient, c.awsClientFactory), iamGroupBuilder(c.iamClient, c.awsClientFactory), } @@ -474,7 +474,7 @@ func (d *defaultCapabilitiesBuilder) Validate(_ context.Context) (annotations.An func (d *defaultCapabilitiesBuilder) ResourceSyncers(_ context.Context) []connectorbuilder.ResourceSyncerV2 { return []connectorbuilder.ResourceSyncerV2{ - iamUserBuilder(nil, nil), + iamUserBuilder(nil, nil, nil), iamRoleBuilder(nil, nil), iamGroupBuilder(nil, nil), ssoUserBuilder("", nil, nil, nil), diff --git a/pkg/connector/iam_user.go b/pkg/connector/iam_user.go index 808bd476..6055a978 100644 --- a/pkg/connector/iam_user.go +++ b/pkg/connector/iam_user.go @@ -5,11 +5,13 @@ import ( "errors" "fmt" "strings" + "sync" "time" awsSdk "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/iam" iamTypes "github.com/aws/aws-sdk-go-v2/service/iam/types" + awsOrgs "github.com/aws/aws-sdk-go-v2/service/organizations" v2 "github.com/conductorone/baton-sdk/pb/c1/connector/v2" "github.com/conductorone/baton-sdk/pkg/annotations" "github.com/conductorone/baton-sdk/pkg/connectorbuilder" @@ -23,6 +25,9 @@ type iamUserResourceType struct { resourceType *v2.ResourceType iamClient *iam.Client awsClientFactory *AWSClientFactory + orgClient *awsOrgs.Client + accountNameMu sync.Mutex + accountNameCache map[string]string } var _ connectorbuilder.AccountManagerV2 = &iamUserResourceType{} @@ -68,6 +73,12 @@ func (o *iamUserResourceType) List(ctx context.Context, parentId *v2.ResourceId, Id: awsSdk.ToString(user.Arn), } profile := iamUserProfile(ctx, user) + if parentId != nil { + profile["aws_account_id"] = parentId.Resource + if accountName := o.getAccountName(ctx, parentId.Resource); accountName != "" { + profile["aws_account_name"] = accountName + } + } lastLogin := getLastLogin(ctx, iamClient, user) options := []resourceSdk.UserTraitOption{ resourceSdk.WithUserProfile(profile), @@ -115,12 +126,41 @@ func (o *iamUserResourceType) Grants(_ context.Context, _ *v2.Resource, _ resour return nil, nil, nil } -func iamUserBuilder(iamClient *iam.Client, awsClientFactory *AWSClientFactory) *iamUserResourceType { +func iamUserBuilder(iamClient *iam.Client, awsClientFactory *AWSClientFactory, orgClient *awsOrgs.Client) *iamUserResourceType { return &iamUserResourceType{ resourceType: resourceTypeIAMUser, iamClient: iamClient, awsClientFactory: awsClientFactory, + orgClient: orgClient, + accountNameCache: make(map[string]string), + } +} + +func (o *iamUserResourceType) getAccountName(ctx context.Context, accountID string) string { + if o.orgClient == nil { + return "" + } + + o.accountNameMu.Lock() + if name, ok := o.accountNameCache[accountID]; ok { + o.accountNameMu.Unlock() + return name + } + o.accountNameMu.Unlock() + + resp, err := o.orgClient.DescribeAccount(ctx, &awsOrgs.DescribeAccountInput{ + AccountId: awsSdk.String(accountID), + }) + if err != nil || resp.Account == nil { + return "" } + + name := awsSdk.ToString(resp.Account.Name) + o.accountNameMu.Lock() + o.accountNameCache[accountID] = name + o.accountNameMu.Unlock() + + return name } func userTagsToMap(u iamTypes.User) map[string]interface{} {