Add support for IAM policies (both managed and inline).#132
Conversation
| }) | ||
| } | ||
|
|
||
| listPoliciesInput := &iam.ListPoliciesInput{} |
There was a problem hiding this comment.
🟡 Suggestion: ListPoliciesInput{} leaves Scope at its default (All), so every sync also pulls the 1000+ AWS-managed policies. Combined with the principal-ARN reconstruction issue above (AWS-managed policy ARNs use account aws), these produce many broken grants and large syncs. If only customer-managed policies are intended, set Scope: types.PolicyScopeTypeLocal. (confidence: medium)
|
@- |
09ed5c9 to
6b4ada0
Compare
| }) | ||
| } | ||
|
|
||
| listPoliciesInput := &iam.ListPoliciesInput{} |
There was a problem hiding this comment.
🟡 Suggestion (medium confidence): ListPolicies with no Scope/OnlyAttached defaults to Scope=All, OnlyAttached=false, which enumerates all ~1000+ AWS-managed policies per account. Each then drives a ListEntitiesForPolicy call in Grants (plus GetUser/GetRole/GetGroup per attached entity), creating many unattached policy resources and a large API/throttling load. Consider OnlyAttached: true (and/or Scope: types.PolicyScopeTypeLocal) to limit to policies actually in use.
| continue | ||
| } | ||
| userARN, err := iamEntityARN(ctx, iamClient, "user", userName) | ||
| if err != nil { | ||
| l.Warn("baton-aws: failed to resolve IAM user ARN for managed policy grant, skipping", | ||
| zap.String("user_name", userName), | ||
| zap.Error(err), | ||
| ) | ||
| continue | ||
| } |
There was a problem hiding this comment.
🟡 Suggestion (low confidence): entity-ARN resolution failures here are logged and skipped for all error types. A transient/throttling error (e.g. 429 on GetUser) would silently drop that principal's grant and under-report access. Consider propagating retryable errors (let the SDK retry) and only skipping on genuine not-found/permanent failures.
| } | ||
|
|
||
| func (o *inlinePolicyResourceType) Grant(_ context.Context, _ *v2.Resource, _ *v2.Entitlement) ([]*v2.Grant, annotations.Annotations, error) { | ||
| return nil, nil, fmt.Errorf("baton-aws: inline policies cannot be created via provisioning") |
There was a problem hiding this comment.
🟡 Suggestion: inline_policy advertises CAPABILITY_PROVISION, but Grant returns a plain fmt.Errorf. Returning status.Errorf(codes.Unimplemented, ...) (matching the gRPC-status convention used in Revoke) lets callers distinguish "unsupported" from a real failure.
Connector PR Review: Add support for IAM policies (both managed and inline).Blocking Issues: 1 | Suggestions: 3 | Threads Resolved: 0 Review SummaryFull PR diff scanned for security and correctness. This PR adds managed ( Security IssuesNone found. Correctness Issues
Suggestions
Prompt for AI agents |
6b4ada0 to
a5d35c0
Compare
| return nil, nil, err | ||
| } | ||
|
|
||
| grants, err := listAttachedUserPolicyGrants(ctx, iamClient, userName, resource.Id) |
There was a problem hiding this comment.
🟡 Suggestion: This propagates an error and hard-fails the whole iam_user Grants phase if ListAttachedUserPolicies returns AccessDenied. role.go handles the equivalent call by logging a Warn and continuing (listAttachedRolePolicyGrants), but here (and in iam_group.go:162 and inline_policy.go List) the error is returned. For existing installs whose IAM policy lacks the newly required iam:ListAttachedUserPolicies / iam:ListGroupPolicies scopes, this turns a missing permission into a full sync failure. Consider degrading gracefully and consistently across all three paths. (confidence: medium)
| listPoliciesInput := &iam.ListPoliciesInput{ | ||
| // TODO: Only list attached policies? |
There was a problem hiding this comment.
🟡 Suggestion: ListPolicies with no Scope defaults to Scope=All / OnlyAttached=false, so this enumerates every AWS-managed policy (~1150) per account on every sync, and iam_policy is a child of each account. Since grants only reference policies that are actually attached, consider Scope: types.PolicyScopeTypeLocal and/or OnlyAttached: true to bound the resource count and per-policy traffic (addresses the existing TODO). (confidence: medium)
a5d35c0 to
3dfcbfc
Compare
11b1a89 to
146a010
Compare
|
I detected this with my automated connector smoke suite. This change is live on the Two things worth considering:
The 403 itself is because our sandbox role ( Happy to share more repro detail. |
9a59fe3 to
d5b7f58
Compare
| grant := grantSdk.NewGrant( | ||
| resource, | ||
| inlinePolicyAttachedEntitlement, | ||
| resource.ParentResourceId, | ||
| grantSdk.WithAnnotation( | ||
| &v2.V1Identifier{ | ||
| Id: V1GrantID( | ||
| V1MembershipEntitlementID(resource.Id), | ||
| resource.ParentResourceId.Resource, | ||
| ), | ||
| }, | ||
| ), | ||
| ) |
There was a problem hiding this comment.
🟡 Suggestion: For group/role parents, this inline-policy grant is emitted without a GrantExpandable annotation, unlike the managed-policy path (grantForAttachedManagedPolicy) which expands group grants to group:...:member (shallow) and role grants to role:...:assignment. AWS inline policies on a group/role apply to members/assumers, so as written those members won't inherit the inline-policy grant. Consider mirroring the managed-policy expansion for group and role principals for consistency. (confidence: medium)
5c7aad1 to
3980aa1
Compare
No description provided.