in source/patterns/@aws-solutions-constructs/core/lib/sagemaker-helper.ts [61:215]
function addPermissions(_role: iam.Role, props?: BuildSagemakerEndpointProps) {
// Grant permissions to NoteBookInstance for creating and training the model
_role.addToPolicy(
new iam.PolicyStatement({
resources: [`arn:${Aws.PARTITION}:sagemaker:${Aws.REGION}:${Aws.ACCOUNT_ID}:*`],
actions: [
'sagemaker:CreateTrainingJob',
'sagemaker:DescribeTrainingJob',
'sagemaker:CreateModel',
'sagemaker:DescribeModel',
'sagemaker:DeleteModel',
'sagemaker:CreateEndpoint',
'sagemaker:CreateEndpointConfig',
'sagemaker:DescribeEndpoint',
'sagemaker:DescribeEndpointConfig',
'sagemaker:DeleteEndpoint',
'sagemaker:DeleteEndpointConfig',
'sagemaker:InvokeEndpoint',
],
})
);
// Grant CloudWatch Logging permissions
_role.addToPolicy(
new iam.PolicyStatement({
resources: [`arn:${cdk.Aws.PARTITION}:logs:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:log-group:/aws/sagemaker/*`],
actions: [
'logs:CreateLogGroup',
'logs:CreateLogStream',
'logs:DescribeLogStreams',
'logs:GetLogEvents',
'logs:PutLogEvents',
],
})
);
// To place the Sagemaker endpoint in a VPC
if (props && props.vpc) {
_role.addToPolicy(
new iam.PolicyStatement({
resources: ['*'],
actions: [
'ec2:CreateNetworkInterface',
'ec2:CreateNetworkInterfacePermission',
'ec2:DeleteNetworkInterface',
'ec2:DeleteNetworkInterfacePermission',
'ec2:DescribeNetworkInterfaces',
'ec2:AssignPrivateIpAddresses',
'ec2:UnassignPrivateIpAddresses',
'ec2:DescribeVpcs',
'ec2:DescribeDhcpOptions',
'ec2:DescribeSubnets',
'ec2:DescribeSecurityGroups',
],
})
);
}
// To create a Sagemaker model using Bring-Your-Own-Model (BYOM) algorith image
// The image URL is specified in the modelProps
_role.addToPolicy(
new iam.PolicyStatement({
resources: [`arn:${cdk.Aws.PARTITION}:ecr:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:repository/*`],
actions: [
'ecr:BatchCheckLayerAvailability',
'ecr:GetDownloadUrlForLayer',
'ecr:DescribeRepositories',
'ecr:DescribeImages',
'ecr:BatchGetImage',
],
})
);
// Add GetAuthorizationToken (it can not be bound to resources other than *)
_role.addToPolicy(
new iam.PolicyStatement({
resources: ['*'],
actions: ['ecr:GetAuthorizationToken'],
})
);
// add permission to use Elastic Inference accelerator
if (props && props.endpointConfigProps) {
// Get the acceleratorType, if any
const acceleratorType = (props.endpointConfigProps
?.productionVariants as sagemaker.CfnEndpointConfig.ProductionVariantProperty[])[0].acceleratorType;
if (acceleratorType !== undefined) {
_role.addToPolicy(
new iam.PolicyStatement({
resources: ['*'],
actions: ['elastic-inference:Connect'],
})
);
}
}
// add kms permissions
_role.addToPolicy(
new iam.PolicyStatement({
// the kmsKeyId in the endpointConfigProps can be any of the following formats:
// Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
// Key ARN: arn:aws:kms:<region>:<accountID>:key/1234abcd-12ab-34cd-56ef-1234567890ab
// Alias name: alias/ExampleAlias
// Alias name ARN: arn:aws:kms:<region>:<accountID>:alias/ExampleAlias
// the key is used to encrypt/decrypt data captured by the Sagemaker endpoint and stored in S3 bucket
resources: [
`arn:${cdk.Aws.PARTITION}:kms:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:key/*`,
`arn:${cdk.Aws.PARTITION}:kms:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:alias/*`,
],
actions: ['kms:Encrypt', 'kms:Decrypt', 'kms:ReEncrypt*', 'kms:GenerateDataKey*', 'kms:DescribeKey'],
})
);
// Add S3 permissions to get Model artifact, put data capture files, etc.
_role.addToPolicy(
new iam.PolicyStatement({
actions: ['s3:GetObject', 's3:PutObject', 's3:DeleteObject', 's3:ListBucket'],
resources: ['arn:aws:s3:::*'],
})
);
// Grant GetRole permissions to the Sagemaker service
_role.addToPolicy(
new iam.PolicyStatement({
resources: [_role.roleArn],
actions: ['iam:GetRole'],
})
);
// Grant PassRole permissions to the Sagemaker service
_role.addToPolicy(
new iam.PolicyStatement({
resources: [_role.roleArn],
actions: ['iam:PassRole'],
conditions: {
StringLike: { 'iam:PassedToService': 'sagemaker.amazonaws.com' },
},
})
);
// Add CFN NAG uppress to allow for "Resource": "*" for ENI access in VPC,
// ECR authorization token for custom model images, and elastic inference
// Add CFN NAG for Complex Role because Sagmaker needs permissions to access several services
const roleDefaultPolicy = _role.node.tryFindChild('DefaultPolicy')?.node.findChild('Resource') as iam.CfnPolicy;
addCfnSuppressRules(roleDefaultPolicy, [
{
id: 'W12',
reason: `Sagemaker needs the following minimum required permissions to access ENIs in a VPC, ECR for custom model images, and elastic inference.`,
},
{
id: 'W76',
reason: 'Complex role becuase Sagemaker needs permissions to access several services',
}
]);
}