in packages/aws-cdk-lib/aws-stepfunctions-tasks/lib/sagemaker/create-training-job.ts [383:493]
private makePolicyStatements(): iam.PolicyStatement[] {
// set the sagemaker role or create new one
this._grantPrincipal = this._role =
this.props.role ||
new iam.Role(this, 'SagemakerRole', {
assumedBy: new iam.ServicePrincipal('sagemaker.amazonaws.com'),
inlinePolicies: {
CreateTrainingJob: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
actions: [
'cloudwatch:PutMetricData',
'logs:CreateLogStream',
'logs:PutLogEvents',
'logs:CreateLogGroup',
'logs:DescribeLogStreams',
'ecr:GetAuthorizationToken',
...(this.props.vpcConfig
? [
'ec2:CreateNetworkInterface',
'ec2:CreateNetworkInterfacePermission',
'ec2:DeleteNetworkInterface',
'ec2:DeleteNetworkInterfacePermission',
'ec2:DescribeNetworkInterfaces',
'ec2:DescribeVpcs',
'ec2:DescribeDhcpOptions',
'ec2:DescribeSubnets',
'ec2:DescribeSecurityGroups',
]
: []),
],
resources: ['*'], // Those permissions cannot be resource-scoped
}),
],
}),
},
});
if (this.props.outputDataConfig.encryptionKey) {
this.props.outputDataConfig.encryptionKey.grantEncrypt(this._role);
}
if (this.props.resourceConfig && this.props.resourceConfig.volumeEncryptionKey) {
this.props.resourceConfig.volumeEncryptionKey.grant(this._role, 'kms:CreateGrant');
}
// create a security group if not defined
if (this.vpc && this.securityGroup === undefined) {
this.securityGroup = new ec2.SecurityGroup(this, 'TrainJobSecurityGroup', {
vpc: this.vpc,
});
this.connections.addSecurityGroup(this.securityGroup);
this.securityGroups.push(this.securityGroup);
}
const stack = Stack.of(this);
// https://docs.aws.amazon.com/step-functions/latest/dg/sagemaker-iam.html
const policyStatements = [
new iam.PolicyStatement({
actions: ['sagemaker:CreateTrainingJob', 'sagemaker:DescribeTrainingJob', 'sagemaker:StopTrainingJob'],
resources: [
stack.formatArn({
service: 'sagemaker',
resource: 'training-job',
// If the job name comes from input, we cannot target the policy to a particular ARN prefix reliably...
resourceName: isJsonPathOrJsonataExpression(this.props.trainingJobName) ? '*' : `${this.props.trainingJobName}*`,
}),
],
}),
new iam.PolicyStatement({
actions: ['sagemaker:ListTags'],
resources: ['*'],
}),
new iam.PolicyStatement({
actions: ['sagemaker:AddTags'],
resources: [
stack.formatArn({
service: 'sagemaker',
resource: 'training-job',
// If the job name comes from input, we cannot target the policy to a particular ARN prefix reliably...
resourceName: sfn.JsonPath.isEncodedJsonPath(this.props.trainingJobName) ? '*' : `${this.props.trainingJobName}*`,
}),
],
}),
new iam.PolicyStatement({
actions: ['iam:PassRole'],
resources: [this._role!.roleArn],
conditions: {
StringEquals: { 'iam:PassedToService': 'sagemaker.amazonaws.com' },
},
}),
];
if (this.integrationPattern === sfn.IntegrationPattern.RUN_JOB) {
policyStatements.push(
new iam.PolicyStatement({
actions: ['events:PutTargets', 'events:PutRule', 'events:DescribeRule'],
resources: [
stack.formatArn({
service: 'events',
resource: 'rule',
resourceName: 'StepFunctionsGetEventsForSageMakerTrainingJobsRule',
}),
],
}),
);
}
return policyStatements;
}