aws-sc-update-constraint-attaches-identity
servicecatalog:UpdateConstraint + iam:PassRole(servicecatalog.amazonaws.com) on a LaunchRole constraint: replace the launch role bound to a product with a more privileged role. The next ProvisionProduct executes as the new launch role. can-execute-as execute-as-via-config-identity-swap propagates with CanPassIdentity to derive CanExecuteAs.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
CanPassIdentity {'new_role': None}
{'product': None} ExecutesAs {'old_role': None}
{'principal': None} HasPermission {'product': None}
where
BuildWorker # AWS::ServiceCatalog::CloudFormationProduct
?product has a LaunchRole constraint with RoleArn = ?old_role
?principal has EFFECTIVE servicecatalog:UpdateConstraint on the constraint associated with ?product
?new_role trust policy allows servicecatalog.amazonaws.com as a trusted service
iam:PassRole for ?new_role permits iam:PassedToService == servicecatalog.amazonaws.com (or unconditioned)
emit
| source type | Identity |
|---|---|
| target type | Compute |
| source | ?principal |
| target | ?product |
| permissions | servicecatalog:UpdateConstraint iam:PassRole |
| conditions | role_compatibility iam_permission |
| state logic | ACTIVE when (a) servicecatalog:UpdateConstraint is in EFFECTIVE policy for the constraint, (b) iam:PassRole for ?new_role is granted with iam:PassedToService including servicecatalog.amazonaws.com or unconditioned, AND (c) ?new_role trust policy allows servicecatalog.amazonaws.com. POTENTIAL(role_compatibility) when ?new_role trust policy does not yet include servicecatalog.amazonaws.com — the constraint update will succeed in changing the RoleArn but Service Catalog will fail to assume the role at provision time. BLOCKED when SCP or permission boundary denies servicecatalog:UpdateConstraint or iam:PassRole at the effective scope. |
Narrative
{principal.name} can update the Launch Role Constraint on product {product.name} (servicecatalog:UpdateConstraint + iam:PassRole for {new_role.name} to servicecatalog.amazonaws.com), modifying the product's execution binding from {old_role.name} to {new_role.name}. The next ProvisionProduct call executes as {new_role.name}. This CanModifyConfiguration + CanPassIdentity chain derives CanExecuteAs via can-execute-as execute-as-via-config-identity-swap.
Raw rule rules/derived/aws/servicecatalog.yaml
id: aws-sc-update-constraint-attaches-identity
emits: CanModifyConfiguration
description: 'servicecatalog:UpdateConstraint + iam:PassRole(servicecatalog.amazonaws.com) on a LaunchRole
constraint: replace the launch role bound to a product with a more privileged role. The next ProvisionProduct
executes as the new launch role. can-execute-as execute-as-via-config-identity-swap propagates with
CanPassIdentity to derive CanExecuteAs.'
match:
- - principal: null
- CanPassIdentity
- new_role: null
- - product: null
- ExecutesAs
- old_role: null
- - principal: null
- HasPermission
- product: null
where:
- 'node_type(?product) == BuildWorker # AWS::ServiceCatalog::CloudFormationProduct'
- ?product has a LaunchRole constraint with RoleArn = ?old_role
- ?principal has EFFECTIVE servicecatalog:UpdateConstraint on the constraint associated with ?product
- ?new_role trust policy allows servicecatalog.amazonaws.com as a trusted service
- iam:PassRole for ?new_role permits iam:PassedToService == servicecatalog.amazonaws.com (or unconditioned)
emit:
source_type: Identity
target_type: Compute
source: ?principal
target: ?product
permissions:
- servicecatalog:UpdateConstraint
- iam:PassRole
conditions:
- role_compatibility
- iam_permission
state_logic: "ACTIVE when (a) servicecatalog:UpdateConstraint is in EFFECTIVE policy for the constraint,\
\ (b) iam:PassRole for ?new_role is granted with iam:PassedToService including servicecatalog.amazonaws.com\
\ or unconditioned, AND (c) ?new_role trust policy allows servicecatalog.amazonaws.com. POTENTIAL(role_compatibility)\
\ when ?new_role trust policy does not yet include servicecatalog.amazonaws.com \u2014 the constraint\
\ update will succeed in changing the RoleArn but Service Catalog will fail to assume the role at\
\ provision time. BLOCKED when SCP or permission boundary denies servicecatalog:UpdateConstraint or\
\ iam:PassRole at the effective scope."
confidence: 0.9
derived_from:
- ?principal CanPassIdentity ?new_role
- ?product ExecutesAs ?old_role
- servicecatalog:UpdateConstraint EFFECTIVE on the constraint
- can-execute-as.yaml execute-as-via-config-identity-swap (CanModifyConfiguration + CanPassIdentity
=> CanExecuteAs)
false_positive_note: 'Honor iam:PassedToService: a role passable only to cloudformation.amazonaws.com,
lambda.amazonaws.com, or ec2.amazonaws.com does NOT satisfy the servicecatalog.amazonaws.com requirement.
Verify the PassedToService condition is either absent (unconditioned) or explicitly includes servicecatalog.amazonaws.com.
Downgrade to POTENTIAL(role_compatibility) when the trust policy or PassedToService condition is ambiguous
or unresolved. can-execute-as execute-as-via-config-identity-swap handles the roll-up with CanPassIdentity;
do not re-derive CanExecuteAs here.'
narrative: '{principal.name} can update the Launch Role Constraint on product {product.name} (servicecatalog:UpdateConstraint
+ iam:PassRole for {new_role.name} to servicecatalog.amazonaws.com), modifying the product''s execution
binding from {old_role.name} to {new_role.name}. The next ProvisionProduct call executes as {new_role.name}.
This CanModifyConfiguration + CanPassIdentity chain derives CanExecuteAs via can-execute-as execute-as-via-config-identity-swap.'