Skip to content

Commit a195149

Browse files
authored
fix: add domain execution role fallback, additional domain tags (#4785)
1 parent cc08418 commit a195149

File tree

3 files changed

+96
-11
lines changed

3 files changed

+96
-11
lines changed

ml_ops/sm-datazone_import/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This example contains python scripts to import an existing SageMaker Domain into
44

55
## Setup
66

7-
1. Add the byod service model
7+
1. Add the Bring-Your-Own-Domain (BYOD) service model
88

99
```bash
1010
aws configure add-model --service-model file://resources/datazone-linkedtypes-2018-05-10.normal.json --service-name datazone-byod
@@ -33,4 +33,9 @@ python import-sagemaker-domain.py \
3333
--region REGION \
3434
--federation-role ARN_OF_FEDERATION_ROLE \
3535
--account-id ACCOUNTID
36-
```
36+
```
37+
38+
### Additional Configuration
39+
40+
- SageMaker execution roles need DataZone API permissions in order for the Assets UI to function. See [DataZoneUserPolicy.json](./resources/DataZoneUserPolicy.json) for an example.
41+
- Ensure the DataZone Domain trusts SageMaker. In the AWS DataZone console navigate to Domain details and select the "Trusted services".

ml_ops/sm-datazone_import/import-sagemaker-domain.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ def _choose_sm_domain(self):
6060
self.sm_domain_name, self.sm_domain_id
6161
)
6262
)
63+
sm_domain = self.sm_client.describe_domain(DomainId=self.sm_domain_id)
64+
self.auth_mode = sm_domain["AuthMode"]
65+
self.default_execution_role = sm_domain["DefaultUserSettings"]["ExecutionRole"]
6366
return self.sm_domain_id
6467

6568
def _choose_dz_domain(self):
@@ -107,15 +110,18 @@ def _choose_dz_project(self):
107110
)
108111
return self.dz_project_id
109112

110-
def _tag_dm_domain(self):
113+
def _tag_sm_domain(self):
111114
# [3.5 Tagging] Before getting started on byod-e2e, ensure that CX has the SM domain and ExecutionRole's tagged accordingly.
112115
# 1. Tag the SM domain by admin (DZ DomainId and tag the stage, and domainAccountId)
113116
# 2. Tag the execution role with DZ domainId and projectId
114117

118+
# TODO - remove project/env tags once front end behavior is fixed
115119
domain_tag = {"Key": "AmazonDataZoneDomain", "Value": self.dz_domain_id}
120+
project_tag = {"Key": "AmazonDataZoneProject", "Value": self.dz_project_id}
121+
env_tag = {"Key": "AmazonDataZoneEnvironment", "Value": self.env_id}
116122
account_tag = {"Key": "AmazonDataZoneDomainAccount", "Value": self.account_id}
117123
stage_tag = {"Key": "AmazonDataZoneStage", "Value": self.stage}
118-
sm_domain_tags = [domain_tag, account_tag, stage_tag]
124+
sm_domain_tags = [domain_tag, project_tag, env_tag, account_tag, stage_tag]
119125
sm_domain_arn = "arn:aws:sagemaker:{}:{}:domain/{}".format(
120126
self.region, self.account_id, self.sm_domain_id
121127
)
@@ -156,9 +162,18 @@ def _map_users(self):
156162
self.sm_user_info = {}
157163
self.sm_user_info["name"] = sm_user_name
158164
self.sm_user_info["arn"] = sm_user_profile_full["UserProfileArn"]
159-
self.sm_user_info["exec_role_arn"] = sm_user_profile_full["UserSettings"][
160-
"ExecutionRole"
161-
]
165+
exec_role = None
166+
if "UserSettings" in sm_user_profile_full:
167+
user_settings = sm_user_profile_full["UserSettings"]
168+
if "ExecutionRole" in user_settings:
169+
exec_role = user_settings["ExecutionRole"]
170+
171+
if exec_role is None:
172+
print(f'User {sm_user_name} has no execution role set, using default from domain.')
173+
exec_role = self.default_execution_role
174+
175+
self.sm_user_info["exec_role_arn"] = exec_role
176+
162177
self.sm_user_info["id"] = sm_user_profile_full[
163178
"HomeEfsFileSystemUid"
164179
] # e.g. d-7d4uvydb9rcy
@@ -170,7 +185,7 @@ def _map_users(self):
170185

171186
# get role name from arn "arn:aws:iam::047923724610:role/service-role/AmazonSageMaker-ExecutionRole-20241008T155288"
172187
role_name = self.sm_user_info["exec_role_arn"][
173-
self.sm_user_info["exec_role_arn"].rfind("/") + 1:
188+
self.sm_user_info["exec_role_arn"].rfind("/") + 1 :
174189
] # rfind searches from back of string
175190
self.iam_client.tag_role(RoleName=role_name, Tags=sm_exec_role_tags)
176191
print(
@@ -360,7 +375,7 @@ def _link_domain(self):
360375
{
361376
"itemIdentifier": f"arn:aws:sagemaker:{self.region}:{self.account_id}:domain/{self.sm_domain_id}",
362377
"itemType": "SAGEMAKER_DOMAIN",
363-
"configuration": {"AuthMode": "NonSSO"},
378+
"configuration": {"AuthMode": self.auth_mode},
364379
"connectedEntities": [
365380
{
366381
"connectedEntityIdentifier": self.env_id,
@@ -464,10 +479,10 @@ def import_interactive(self):
464479
self._choose_sm_domain()
465480
self._choose_dz_domain()
466481
self._choose_dz_project()
467-
self._tag_dm_domain()
482+
self._configure_environment()
483+
self._tag_sm_domain()
468484
self._map_users()
469485
self._configure_blueprint()
470-
self._configure_environment()
471486
self._add_environment_action()
472487
self._associate_fed_role()
473488
self._link_domain()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"Statement": [
3+
{
4+
"Condition": {
5+
"StringEquals": {
6+
"iam:PassedToService": "datazone.amazonaws.com"
7+
}
8+
},
9+
"Action": [
10+
"iam:PassRole"
11+
],
12+
"Resource": [
13+
"arn:aws:iam::*:role/AmazonDataZone*",
14+
"arn:aws:iam::*:role/service-role/AmazonDataZone*"
15+
],
16+
"Effect": "Allow"
17+
},
18+
{
19+
"Action": [
20+
"datazone:AcceptSubscriptionRequest",
21+
"datazone:CreateSubscriptionRequest",
22+
"datazone:CreateDataSource",
23+
"datazone:DeleteSubscriptionRequest",
24+
"datazone:Search",
25+
"datazone:SearchListings",
26+
"datazone:ListSubscriptionRequests",
27+
"datazone:ListAssetRevisions",
28+
"datazone:GetListing",
29+
"datazone:GetAsset",
30+
"datazone:GetEnvironment",
31+
"datazone:GetProject",
32+
"datazone:RejectSubscriptionRequest",
33+
"datazone:CancelSubscription",
34+
"datazone:ListSubscriptions",
35+
"datazone:ListDataSources",
36+
"datazone:ListDataSourceRuns",
37+
"datazone:ListDataSourceRunActivities",
38+
"datazone:GetDataSource",
39+
"datazone:GetDataSourceRun",
40+
"datazone:StartDataSourceRun",
41+
"datazone:UpdateDataSource",
42+
"datazone:DeleteDataSource",
43+
"datazone:ListEnvironments",
44+
"datazone:CreateListingChangeSet",
45+
"datazone:RevokeSubscription",
46+
"datazone:GetGlossaryTerm",
47+
"datazone:CreateAsset",
48+
"datazone:CreateAssetRevision",
49+
"datazone:GetUserProfile",
50+
"datazone:GetUserProfile",
51+
"datazone:ListSubscriptionGrants",
52+
"datazone:CreateSubscriptionGrant",
53+
"datazone:GetSubscriptionGrant",
54+
"datazone:DeleteAsset",
55+
"datazone:DeleteDataSource",
56+
"datazone:GetFormType",
57+
"datazone:ListGroupsForUser",
58+
"datazone:ListProjectMemberships",
59+
"datazone:DeleteListing"
60+
],
61+
"Resource": "*",
62+
"Effect": "Allow"
63+
}
64+
]
65+
}

0 commit comments

Comments
 (0)