This is issue is related to #52
Summary
When a user clicks Script on a Glue job in the SageMaker Unified Studio (SMUS) Data Processing Jobs view, the script content fails to load with an s3:GetObject explicit-deny error. The project S3 bucket's catch-all deny policy fires against the SMUS user role (datazone_usr_role_<projectId>_<userId>) because that role is not in any allow list and is not excluded from the deny.
Affected version
@aws-mdaa/dataops-project v1.5.0
Component
packages/constructs/L3/dataops/dataops-project-l3-construct/lib/dataops-project-l3-construct.ts
createProjectBucket — bucket policy construction
Error message
Error loading script: User: arn:aws:sts::<account>:assumed-role/datazone_usr_role_<projectId>_<userId>/<sessionId>
is not authorized to perform: s3:GetObject on resource:
"arn:aws:s3:::test123-dev-dataops-project123/deployment/jobs/counts/counts.py"
with an explicit deny in a resource-based policy
Root cause
dataops-project creates two distinct DataZone-related IAM roles:
| Role |
Created by |
Purpose |
<prefix>-dz-user |
MDAA (createDatazoneUserRole) |
DataZone environment operations; assumable by datazone.amazonaws.com |
datazone_usr_role_<projectId>_<userId> |
SMUS dynamically at session time |
Individual user Studio sessions in SMUS |
The MDAA-created dz-user role is excluded from the bucket's catch-all deny policy and is allowed on /athena-results. The SMUS user role, however, is created by AWS at the moment a user opens the SMUS Studio -- it is not known to MDAA at deploy time and therefore appears nowhere in the bucket policy.
The project bucket's deny statement uses a ForAnyValue:StringNotLike condition on aws:userId (role IDs) and aws:PrincipalArn (exact ARNs). Because datazone_usr_role_* is in neither list, the catch-all deny fires:
Effect: Deny
Action: [s3:PutObject*, s3:GetObject*, s3:DeleteObject*]
Condition:
ForAnyValue:StringNotLike:
aws:userId: [AROAXX:*, AROAYY:*, ...] ← execution roles, admin roles, dz-user
aws:PrincipalArn: [arn:.../deployment-role]
The explicit deny overrides any allow elsewhere. No separate allow for the /deployment prefix was present either -- that prefix was only open to execution roles (Glue runners) and the CDK deployer.
AWS SMUS creates roles following the pattern datazone_usr_role_<projectId>_<userId> for all users who access the Studio. This is a well-documented AWS naming convention, account-scoped, and safe to use in IAM wildcard patterns within the same account.
Proposed Fix
Two additions inside createProjectBucket:
1. Allow s3:GetObject* on deployment/* for SMUS user roles
const smusUserRoleArnPattern = `arn:aws:iam::${this.account}:role/datazone_usr_role_*`;
const smusUserRoleDeploymentRead = new PolicyStatement({
sid: 'SmusUserRoleDeploymentRead',
effect: Effect.ALLOW,
actions: RestrictObjectPrefixToRoles.READ_ACTIONS,
resources: [projectBucket.arnForObjects('deployment/*')],
conditions: { StringLike: { 'aws:PrincipalArn': smusUserRoleArnPattern } },
});
smusUserRoleDeploymentRead.addAnyPrincipal();
projectBucket.addToResourcePolicy(smusUserRoleDeploymentRead);
2. Exempt SMUS user roles from the catch-all deny
const bucketRestrictPolicy = new RestrictBucketToRoles({
...
principalExcludes: [
projectDeploymentRole.roleArn,
smusUserRoleArnPattern, // <-- new
],
});
This adds arn:aws:iam::<account>:role/datazone_usr_role_* to the aws:PrincipalArn values in the ForAnyValue:StringNotLike deny condition. When the SMUS user role's ARN matches the pattern, the deny does not fire, and the explicit allow on deployment/* takes effect.
Scope of the wildcard:
arn:aws:iam::<account>:role/datazone_usr_role_* is:
- Scoped to the same AWS account so no cross-account exposure
- Limited to AWS SMUS-generated user roles by naming convention
- Read-only on
deployment/* (Glue scripts); no write, no data/*, no temp/*
- Consistent with how the existing
dz-user role is treated (excluded from deny, allowed on /athena-results)
Impact
This is issue is related to #52
Summary
When a user clicks Script on a Glue job in the SageMaker Unified Studio (SMUS) Data Processing Jobs view, the script content fails to load with an
s3:GetObjectexplicit-deny error. The project S3 bucket's catch-all deny policy fires against the SMUS user role (datazone_usr_role_<projectId>_<userId>) because that role is not in any allow list and is not excluded from the deny.Affected version
@aws-mdaa/dataops-projectv1.5.0Component
packages/constructs/L3/dataops/dataops-project-l3-construct/lib/dataops-project-l3-construct.tscreateProjectBucket— bucket policy constructionError message
Root cause
dataops-projectcreates two distinct DataZone-related IAM roles:<prefix>-dz-usercreateDatazoneUserRole)datazone.amazonaws.comdatazone_usr_role_<projectId>_<userId>The MDAA-created
dz-userrole is excluded from the bucket's catch-all deny policy and is allowed on/athena-results. The SMUS user role, however, is created by AWS at the moment a user opens the SMUS Studio -- it is not known to MDAA at deploy time and therefore appears nowhere in the bucket policy.The project bucket's deny statement uses a
ForAnyValue:StringNotLikecondition onaws:userId(role IDs) andaws:PrincipalArn(exact ARNs). Becausedatazone_usr_role_*is in neither list, the catch-all deny fires:The explicit deny overrides any allow elsewhere. No separate allow for the
/deploymentprefix was present either -- that prefix was only open to execution roles (Glue runners) and the CDK deployer.AWS SMUS creates roles following the pattern
datazone_usr_role_<projectId>_<userId>for all users who access the Studio. This is a well-documented AWS naming convention, account-scoped, and safe to use in IAM wildcard patterns within the same account.Proposed Fix
Two additions inside
createProjectBucket:1. Allow
s3:GetObject*ondeployment/*for SMUS user roles2. Exempt SMUS user roles from the catch-all deny
This adds
arn:aws:iam::<account>:role/datazone_usr_role_*to theaws:PrincipalArnvalues in theForAnyValue:StringNotLikedeny condition. When the SMUS user role's ARN matches the pattern, the deny does not fire, and the explicit allow ondeployment/*takes effect.Scope of the wildcard:
arn:aws:iam::<account>:role/datazone_usr_role_*is:deployment/*(Glue scripts); no write, nodata/*, notemp/*dz-userrole is treated (excluded from deny, allowed on/athena-results)Impact
dataops-jobwith SMUS users accessing the Studio.