Skip to content

Commit da692d2

Browse files
author
Roja Reddy Sareddy
committed
refactor(evaluate): Use evaluation role type via iam_role_resolver
Add 'evaluation' role type to IAM_POLICY_CONFIG with Bedrock and MLflow permissions. BaseEvaluator now calls resolve_and_validate_role with role_type='evaluation' which validates permissions and trust using the existing iam_role_resolver infrastructure. Removes the standalone role_permission_validator utility in favor of the existing centralized approach.
1 parent bfc1047 commit da692d2

5 files changed

Lines changed: 311 additions & 371 deletions

File tree

‎sagemaker-core/src/sagemaker/core/helper/iam_policies.py‎

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,4 +812,149 @@
812812
},
813813
},
814814
},
815+
"evaluation": {
816+
"role_name": "SageMaker-AutoRole-Evaluation",
817+
"trust_policy": {
818+
"Version": "2012-10-17",
819+
"Statement": [
820+
{
821+
"Effect": "Allow",
822+
"Principal": {
823+
"Service": [
824+
"sagemaker.amazonaws.com",
825+
"bedrock.amazonaws.com",
826+
]
827+
},
828+
"Action": "sts:AssumeRole",
829+
"Condition": {
830+
"StringEquals": {"aws:SourceAccount": "ACCOUNT_PLACEHOLDER"}
831+
},
832+
}
833+
],
834+
},
835+
"policies": {
836+
# --- Training permissions (superset of "training" role type) ---
837+
"s3_policy": {
838+
"Version": "2012-10-17",
839+
"Statement": [
840+
{
841+
"Effect": "Allow",
842+
"Action": [
843+
"s3:GetObject",
844+
"s3:PutObject",
845+
"s3:ListBucket",
846+
"s3:GetBucketLocation",
847+
],
848+
"Resource": "S3_PLACEHOLDER",
849+
}
850+
],
851+
},
852+
"ecr_policy": {
853+
"Version": "2012-10-17",
854+
"Statement": [
855+
{
856+
"Effect": "Allow",
857+
"Action": ["ecr:GetAuthorizationToken"],
858+
"Resource": "*",
859+
},
860+
{
861+
"Effect": "Allow",
862+
"Action": [
863+
"ecr:GetDownloadUrlForLayer",
864+
"ecr:BatchGetImage",
865+
"ecr:BatchCheckLayerAvailability",
866+
],
867+
"Resource": "arn:aws:ecr:*:*:repository/*",
868+
},
869+
],
870+
},
871+
"cloudwatch_policy": {
872+
"Version": "2012-10-17",
873+
"Statement": [
874+
{
875+
"Effect": "Allow",
876+
"Action": ["cloudwatch:PutMetricData"],
877+
"Resource": "*",
878+
},
879+
{
880+
"Effect": "Allow",
881+
"Action": [
882+
"logs:CreateLogGroup",
883+
"logs:CreateLogStream",
884+
"logs:PutLogEvents",
885+
"logs:DescribeLogStreams",
886+
],
887+
"Resource": "arn:aws:logs:*:*:log-group:/aws/sagemaker/TrainingJobs*",
888+
},
889+
],
890+
},
891+
"kms_policy": {
892+
"Version": "2012-10-17",
893+
"Statement": [
894+
{
895+
"Effect": "Allow",
896+
"Action": ["kms:Encrypt", "kms:Decrypt", "kms:GenerateDataKey"],
897+
"Resource": "KMS_PLACEHOLDER",
898+
}
899+
],
900+
},
901+
# --- Evaluation-specific permissions ---
902+
"bedrock_evaluation_policy": {
903+
"Version": "2012-10-17",
904+
"Statement": [
905+
{
906+
"Effect": "Allow",
907+
"Action": [
908+
"bedrock:CreateEvaluationJob",
909+
"bedrock:GetEvaluationJob",
910+
"bedrock:InvokeModel",
911+
"bedrock:InvokeModelWithResponseStream",
912+
],
913+
"Resource": "*",
914+
}
915+
],
916+
},
917+
"mlflow_policy": {
918+
"Version": "2012-10-17",
919+
"Statement": [
920+
{
921+
"Effect": "Allow",
922+
"Action": [
923+
"sagemaker-mlflow:GetExperimentByName",
924+
"sagemaker-mlflow:CreateExperiment",
925+
"sagemaker-mlflow:CreateRun",
926+
"sagemaker-mlflow:LogBatch",
927+
"sagemaker-mlflow:LogMetric",
928+
"sagemaker-mlflow:LogParam",
929+
"sagemaker-mlflow:SetTag",
930+
"sagemaker-mlflow:UpdateRun",
931+
],
932+
"Resource": "arn:aws:sagemaker:*:*:mlflow-app/*",
933+
}
934+
],
935+
},
936+
"sagemaker_evaluation_policy": {
937+
"Version": "2012-10-17",
938+
"Statement": [
939+
{
940+
"Effect": "Allow",
941+
"Action": [
942+
"sagemaker:CreateTrainingJob",
943+
"sagemaker:DescribeTrainingJob",
944+
"sagemaker:StopTrainingJob",
945+
"sagemaker:CreatePipeline",
946+
"sagemaker:DescribePipeline",
947+
"sagemaker:StartPipelineExecution",
948+
"sagemaker:DescribePipelineExecution",
949+
"sagemaker:AddTags",
950+
],
951+
"Resource": [
952+
"arn:aws:sagemaker:*:*:training-job/*",
953+
"arn:aws:sagemaker:*:*:pipeline/*",
954+
],
955+
}
956+
],
957+
},
958+
},
959+
},
815960
}

‎sagemaker-core/src/sagemaker/core/helper/iam_role_resolver.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525

2626
logger = logging.getLogger(__name__)
2727

28-
ROLE_TYPES = ("training", "serving", "pipeline", "feature_store", "bedrock", "hyperpod")
28+
ROLE_TYPES = ("training", "serving", "pipeline", "feature_store", "bedrock", "hyperpod", "evaluation")
2929

3030
# Permissions the HyperPod CLI flow needs on the *caller* identity — the local
3131
# principal that runs `hyperpod connect-cluster` and `hyperpod start-job`. The CLI

‎sagemaker-train/src/sagemaker/train/common_utils/role_permission_validator.py‎

Lines changed: 0 additions & 195 deletions
This file was deleted.

‎sagemaker-train/src/sagemaker/train/evaluate/base_evaluator.py‎

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@
3030
_is_nova_model,
3131
)
3232
from sagemaker.train.common_utils.recipe_utils import resolve_recipe, get_resolved_recipe_from_context
33-
from sagemaker.train.common_utils.role_permission_validator import (
34-
validate_evaluation_role_permissions,
35-
)
3633
from sagemaker.train.common_utils.validator import validate_hyperpod_compute
3734
from sagemaker.train.defaults import TrainDefaults
3835
from sagemaker.train.recipe_resolver import flatten_resolved_recipe
@@ -737,10 +734,10 @@ def _get_aws_execution_context(self) -> Dict[str, str]:
737734
# This is the job execution role for the
738735
# serverless / SMTJ evaluation backends. The HyperPod backend submits via
739736
# the CLI under the caller's own credentials (see _submit_hyperpod_eval_job)
740-
# and does not resolve a role here, so "training" is always correct here.
737+
# and does not resolve a role here, so "evaluation" is correct here.
741738
role_arn = resolve_and_validate_role(
742739
provided_role=self.role,
743-
role_type="training",
740+
role_type="evaluation",
744741
sagemaker_session=self.sagemaker_session,
745742
)
746743

@@ -751,13 +748,6 @@ def _get_aws_execution_context(self) -> Dict[str, str]:
751748

752749
# Extract account ID from role ARN
753750
account_id = role_arn.split(':')[4] if ':' in role_arn else '052150106756'
754-
755-
# Validate execution role has permissions required for evaluation
756-
validate_evaluation_role_permissions(
757-
role_arn,
758-
self.sagemaker_session,
759-
mlflow_enabled=bool(getattr(self, 'mlflow_resource_arn', None)),
760-
)
761751

762752
return {
763753
'role_arn': role_arn,

0 commit comments

Comments
 (0)