Amazon SageMaker AI
Connect Amazon SageMaker AI to Safeguard. The exact IAM policy the read-only role needs, which credentials work, and step-by-step setup with CloudFormation, Terraform or the AWS CLI.
Availability
This integration is switched on per workspace. If you do not see the card under Integrations, ask your Safeguard contact.
What it does
Safeguard reads an inventory of the AI assets you run in Amazon SageMaker AI (including JumpStart): models, Model Registry groups and versions, real-time endpoints and their endpoint configurations, and inference components, in every region the connection reads. For each one it records where the model came from (JumpStart, your own S3 or Model Registry, or unknown), whether the endpoint serves a pinned version, network isolation, the customer-managed key on the endpoint's storage, and how broad each execution role is. The results appear as AI asset inventory entries and continuous tests (asset inventory, public access, network isolation, customer-managed keys, least-privilege execution roles, pinned model versions, licence risk and model provenance). Find the Amazon SageMaker AI card under Integrations on the Project/Product tab (the AI Model filter shows only AI model cards). Safeguard never invokes an endpoint, and no customer data goes to third-party LLMs.
This is a separate connection from the AWS compliance connection: its role holds only the SageMaker AI reads below, and the AWS compliance tests never run on it.
Public vs private
| Public | Private | |
|---|---|---|
| What you enter | Nothing: there is no public mode | A cross-account role ARN (or an IAM user's access key) and, optionally, the regions to read |
| Credential needed | Not applicable | A role or IAM user with the Safeguard ML inventory policy |
| What you can scan | Not applicable | Every SageMaker AI model, endpoint, inference component and Model Registry entry in the regions read |
Supported auth methods
| Method | Use it when | Notes |
|---|---|---|
| Cross-account IAM role with an external ID | The recommended default | Safeguard assumes the role with the external ID it generates for this connection; no long-lived key leaves your account |
| IAM user access key | Your installation has no AWS platform principal, or your policy forbids cross-account roles | Attach the same policy to the user; rotate the key yourself |
Permissions required
Safeguard only reads. Every action below is a List, Describe or Get call; there is no write action and no data-plane action (Safeguard never calls sagemaker:InvokeEndpoint). The least-privilege choice is the inline policy below on a dedicated role. Do not use the AWS managed policy AmazonSageMakerReadOnly: it also grants Feature Store record reads (sagemaker:GetRecord, sagemaker:BatchGetRecord), sagemaker:Search and Cognito user lists, which Safeguard does not need.
Cross-account IAM role with an external ID
| Permission / scope | Required? | What Safeguard uses it for |
|---|---|---|
sts:AssumeRole for Safeguard's principal, with the condition sts:ExternalId (in the role's trust policy) | Required | Lets Safeguard assume the role, only with this connection's external ID |
sagemaker:ListModels | Required | Lists the models in each region |
sagemaker:DescribeModel | Required | Each model's containers (image, model data location, JumpStart hub content, Model Registry package), execution role, VPC and network isolation |
sagemaker:ListEndpoints | Required | Lists the endpoints in each region (also the action Check access tries) |
sagemaker:DescribeEndpoint | Required | Each endpoint's configuration name, status and deployed images |
sagemaker:DescribeEndpointConfig | Required | Each endpoint's production variants (model, instance type, serverless), KMS key, execution role, VPC and network isolation |
sagemaker:ListInferenceComponents | Required | Lists the inference components in each region |
sagemaker:DescribeInferenceComponent | Required | Each inference component's endpoint, model, deployed image and status |
sagemaker:ListModelPackageGroups | Required | Lists the Model Registry groups |
sagemaker:ListModelPackages | Required | Lists the versions in each Model Registry group |
sagemaker:DescribeModelPackage | Required | Each registry version's containers, image digest, model data location, JumpStart base model and approval status |
sagemaker:ListTags | Required | The JumpStart tags the SageMaker Python SDK and Studio add (model id, version, model type, hub content ARN) |
sagemaker:DescribeHubContent | Required | A JumpStart model's display name and support status (Supported, Deprecated, Restricted) |
iam:ListAttachedRolePolicies | Required | Which managed policies each execution role holds, to judge how broad it is |
iam:ListRolePolicies | Required | Which inline policies each execution role holds |
iam:GetRolePolicy | Required | Reads each inline policy document (never the role's credentials) |
ec2:DescribeRegions | Required | Finds the account's enabled regions; not needed when the connection lists its regions |
s3:GetObject | Optional | Reserved for a later model-artifact scan; off by default and not used today. If you ever grant it, grant it only on the buckets that hold model artifacts |
The exact permissions policy (the setup steps in the app show the same JSON with a copy button):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SafeguardSageMakerInventoryRead",
"Effect": "Allow",
"Action": [
"sagemaker:ListModels",
"sagemaker:DescribeModel",
"sagemaker:ListEndpoints",
"sagemaker:DescribeEndpoint",
"sagemaker:DescribeEndpointConfig",
"sagemaker:ListInferenceComponents",
"sagemaker:DescribeInferenceComponent",
"sagemaker:ListModelPackageGroups",
"sagemaker:ListModelPackages",
"sagemaker:DescribeModelPackage",
"sagemaker:ListTags",
"sagemaker:DescribeHubContent"
],
"Resource": "*"
},
{
"Sid": "SafeguardExecutionRoleBreadthRead",
"Effect": "Allow",
"Action": [
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:GetRolePolicy"
],
"Resource": "*"
},
{
"Sid": "SafeguardRegionsRead",
"Effect": "Allow",
"Action": [
"ec2:DescribeRegions"
],
"Resource": "*"
}
]
}The trust policy. In the app, <SAFEGUARD_PRINCIPAL_ARN> and <EXTERNAL_ID> are filled in for your connection:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "<SAFEGUARD_PRINCIPAL_ARN>"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<EXTERNAL_ID>"
}
}
}
]
}Least privilege: the role SafeguardMlInventory with exactly the policy above. If the connection lists its regions, you may drop ec2:DescribeRegions. Without the three iam: actions the inventory still works, but every execution role is reported as not judged.
IAM user access key
| Permission / scope | Required? | What Safeguard uses it for |
|---|---|---|
| The permissions policy above, attached to the IAM user | Required | The same reads as the role, signed with the user's key |
s3:GetObject | Optional | Reserved for a later model-artifact scan; not used today |
Least privilege: a dedicated IAM user with only the policy above as an inline policy, no console password and one active access key.
Token types
| Token type | Works? | Notes |
|---|---|---|
| Role assumed with an external ID (temporary credentials) | Yes (recommended) | The template sets MaxSessionDuration to 3600 seconds; Safeguard assumes the role again for each run |
| IAM user access key (access key ID and secret access key) | Yes | Long-lived: rotate it on a schedule |
| Read-only vs admin | Read-only only | The policy above holds only reads; Safeguard never needs an administrator role |
AWS managed policy AmazonSageMakerReadOnly | Not recommended | Broader than needed (Feature Store records, Search, Cognito user lists) |
| Root user keys | No | Never use root credentials |
Expiry: role sessions end after at most one hour and are renewed automatically, so the role itself has nothing to rotate. An access key does not expire on its own: rotate it at least every 90 days.
What we never need: any write action, sagemaker:InvokeEndpoint or any other data-plane access, AmazonSageMakerReadOnly, AdministratorAccess, s3:GetObject today, or root credentials. A model's Environment variables can hold secrets: Safeguard drops them from every response unread and never stores them.
Step-by-step setup
Get the external ID from Safeguard (cross-account role)
- Open Integrations and choose the Project/Product tab (optionally the AI Model filter).
- Click Connect on the Amazon SageMaker AI card.
- Give the connection a name, choose the cross-account role method, and save. Safeguard generates the connection's external ID on this first save; you cannot choose it.
- The dialog now shows the external ID, and its Setup steps section shows the CloudFormation template, the AWS CLI commands, the Terraform, the permissions policy and the trust policy with your external ID and Safeguard's principal filled in. Each has a copy button.
Create the credential in Amazon SageMaker AI
- Copy the CloudFormation template from Setup steps and save it as
safeguard-ml-inventory.yaml. - In the AWS console, open CloudFormation > Create stack > With new resources, upload the file, and acknowledge that it creates a named IAM role.
- When the stack finishes, open its Outputs tab and copy RoleArn.
The template, with placeholders where the app fills in your values:
AWSTemplateFormatVersion: '2010-09-09'
Description: Safeguard ML inventory - read-only access to Amazon SageMaker AI (no write action, no data plane).
Resources:
SafeguardMlInventoryRole:
Type: AWS::IAM::Role
Properties:
RoleName: SafeguardMlInventory
MaxSessionDuration: 3600
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: '<SAFEGUARD_PRINCIPAL_ARN>'
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: '<EXTERNAL_ID>'
Policies:
- PolicyName: SafeguardMlInventoryRead
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: SafeguardSageMakerInventoryRead
Effect: Allow
Action:
- sagemaker:ListModels
- sagemaker:DescribeModel
- sagemaker:ListEndpoints
- sagemaker:DescribeEndpoint
- sagemaker:DescribeEndpointConfig
- sagemaker:ListInferenceComponents
- sagemaker:DescribeInferenceComponent
- sagemaker:ListModelPackageGroups
- sagemaker:ListModelPackages
- sagemaker:DescribeModelPackage
- sagemaker:ListTags
- sagemaker:DescribeHubContent
Resource: '*'
- Sid: SafeguardExecutionRoleBreadthRead
Effect: Allow
Action:
- iam:ListAttachedRolePolicies
- iam:ListRolePolicies
- iam:GetRolePolicy
Resource: '*'
- Sid: SafeguardRegionsRead
Effect: Allow
Action:
- ec2:DescribeRegions
Resource: '*'
Outputs:
RoleArn:
Description: Paste this into the Safeguard connection.
Value: !GetAtt SafeguardMlInventoryRole.ArnOr with the AWS CLI
Deploy the same template and print the role ARN:
aws cloudformation deploy --stack-name safeguard-ml-inventory --template-file safeguard-ml-inventory.yaml --capabilities CAPABILITY_NAMED_IAM
aws cloudformation describe-stacks --stack-name safeguard-ml-inventory --query "Stacks[0].Outputs[?OutputKey=='RoleArn'].OutputValue" --output textOr with Terraform
resource "aws_iam_role" "safeguard_ml_inventory" {
name = "SafeguardMlInventory"
max_session_duration = 3600
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { AWS = "<SAFEGUARD_PRINCIPAL_ARN>" }
Action = "sts:AssumeRole"
Condition = { StringEquals = { "sts:ExternalId" = "<EXTERNAL_ID>" } }
}]
})
}
resource "aws_iam_role_policy" "safeguard_ml_inventory_read" {
name = "SafeguardMlInventoryRead"
role = aws_iam_role.safeguard_ml_inventory.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{ Sid = "SafeguardSageMakerInventoryRead", Effect = "Allow", Action = ["sagemaker:ListModels", "sagemaker:DescribeModel", "sagemaker:ListEndpoints", "sagemaker:DescribeEndpoint", "sagemaker:DescribeEndpointConfig", "sagemaker:ListInferenceComponents", "sagemaker:DescribeInferenceComponent", "sagemaker:ListModelPackageGroups", "sagemaker:ListModelPackages", "sagemaker:DescribeModelPackage", "sagemaker:ListTags", "sagemaker:DescribeHubContent"], Resource = "*" },
{ Sid = "SafeguardExecutionRoleBreadthRead", Effect = "Allow", Action = ["iam:ListAttachedRolePolicies", "iam:ListRolePolicies", "iam:GetRolePolicy"], Resource = "*" },
{ Sid = "SafeguardRegionsRead", Effect = "Allow", Action = ["ec2:DescribeRegions"], Resource = "*" },
]
})
}
output "safeguard_role_arn" {
value = aws_iam_role.safeguard_ml_inventory.arn
}Or with an IAM user access key
Save the permissions policy above as safeguard-ml-inventory-policy.json, then:
aws iam create-user --user-name safeguard-ml-inventory
aws iam put-user-policy --user-name safeguard-ml-inventory --policy-name SafeguardMlInventoryRead --policy-document file://safeguard-ml-inventory-policy.json
aws iam create-access-key --user-name safeguard-ml-inventoryCopy the access key ID and secret access key. AWS shows the secret only once.
Connect it in Safeguard
- Back in the Amazon SageMaker AI dialog, paste the role ARN from the stack output (or, for the access key method, the access key ID and secret access key).
- Optionally list the regions to read. Leave it empty to read every enabled region of the account.
- Save, then click Check access. Safeguard assumes the role (or uses the key) and lists one SageMaker AI endpoint. Success reads
Read SageMaker AI in <region> as <role ARN>.A failure names the missing permission (see Troubleshooting).
Check access tries one action, sagemaker:ListEndpoints. If another action from the policy is missing, the next test run shows an error row for that region that names it.
Webhooks and triggers
This integration has no webhooks. The inventory is read each time the connection's tests run, on their schedule or when you run them by hand.
What we read and store
- Read: the configuration of models, endpoints, endpoint configurations, inference components and Model Registry groups and versions; the JumpStart tags and catalog entries they name; the managed and inline policies of each execution role in the same account (to judge breadth, never its credentials); the account's enabled regions.
- Stored: the inventory (names, ARNs, regions, images, model data locations, JumpStart model ids and versions, instance types, network, encryption and execution role findings) in the AI asset inventory, and the test results. An asset that disappears is marked inactive, not deleted. Access keys are encrypted at rest and never shown again after you save them.
- Not stored or read: predictions and endpoint invocations, model artifacts in S3, training data, Feature Store records, and the containers'
Environmentvariables. Model Registry model cards, metrics, drift baselines and custom metadata are dropped unread. - No customer data from this integration is sent to third-party LLMs.
Troubleshooting
| Message you see | Cause | Fix |
|---|---|---|
Safeguard could not assume <role ARN>: deploy the SafeguardMlInventory template from the setup steps, trusting this installation's principal with this connection's external ID. | The role does not exist, or its trust policy names another principal or external ID | Deploy the template from Setup steps (it carries this connection's external ID), or fix the trust policy |
The role was assumed but cannot list SageMaker AI endpoints: attach the Safeguard ML inventory policy from the setup steps (it needs sagemaker:ListEndpoints and the other read actions). | The role exists but lacks the permissions policy | Attach the permissions policy above to the role |
The platform role method needs the ARN of the role Safeguard assumes in your account. | The role ARN is empty | Paste the RoleArn output of the stack |
This connection has no external ID yet; save it again so the server can generate one. | The connection was not saved before the role step | Save the connection, then copy the template again |
This installation has no AWS platform principal to assume a role with; use an access key. | This Safeguard installation cannot assume roles | Use the IAM user access key method |
AWS needs an access key id and a secret access key on this connection. | One of the key fields is empty | Enter both the access key ID and the secret access key |
The role ARN is not in the AWS partition <partition>. | The ARN belongs to another partition (for example GovCloud) | Use the role ARN from the same partition as the connection |
Region(s) <regions> are not in the AWS partition <partition>. | A listed region is not in the connection's partition | Correct or remove the region |
... AWS did not accept the connection's credential. | The access key was deleted, deactivated or mistyped | Create a new access key and update the connection |
sagemaker:ListTags refused in <region>: JumpStart tags were not read there | The policy lacks sagemaker:ListTags | Add it; until then JumpStart models in that region may show as unknown provenance |
sagemaker:DescribeHubContent failed for <model>: <code> | The JumpStart catalog entry could not be read | Add sagemaker:DescribeHubContent; the model is still inventoried without its display name |
IAM refused reading the role's policies (<code>): grant iam:ListAttachedRolePolicies, iam:ListRolePolicies and iam:GetRolePolicy | The policy lacks the three iam: actions | Add them; until then execution roles are not judged |
the role is in another account, which this connection does not read | An execution role lives in another AWS account | Nothing to fix: that role is reported as not judged |
...: the service is not offered to this account in this region. | SageMaker AI is not available in a listed region | Remove the region from the connection |
Rotation and disconnect
- Rotate: a role has nothing to rotate. For an access key, create a second key (
aws iam create-access-key --user-name safeguard-ml-inventory), paste it into the connection and save, then delete the old one (aws iam delete-access-key --user-name safeguard-ml-inventory --access-key-id <OLD_KEY_ID>). - Disconnect: delete the connection in Safeguard, then delete the stack (
aws cloudformation delete-stack --stack-name safeguard-ml-inventory), runterraform destroyon the role, or delete the IAM user and its keys.
Vendor references
- ListModels, checked 2026-10-16.
- DescribeModel, checked 2026-10-16.
- ListEndpoints, checked 2026-10-16.
- DescribeEndpoint, checked 2026-10-16.
- DescribeEndpointConfig, checked 2026-10-16.
- ListInferenceComponents, checked 2026-10-16.
- DescribeInferenceComponent, checked 2026-10-16.
- ListModelPackageGroups, checked 2026-10-16.
- ListModelPackages, checked 2026-10-16.
- DescribeModelPackage, checked 2026-10-16.
- ListTags, checked 2026-10-16.
- DescribeHubContent, checked 2026-10-16.
- InferenceHubAccessConfig, checked 2026-10-16.
- IAM ListAttachedRolePolicies, checked 2026-10-16.
- IAM ListRolePolicies, checked 2026-10-16.
- IAM GetRolePolicy, checked 2026-10-16.
- AmazonSageMakerReadOnly managed policy, checked 2026-10-16.
- SageMaker Python SDK JumpStart tags (enums.py), checked 2026-10-16.
ModelScope
Connect ModelScope to Safeguard. The SDK token a private connection needs, which token tiers work, what Safeguard reads, and step-by-step setup.
Google Vertex AI
Connect Google Vertex AI to Safeguard. The roles and custom role permissions the service account needs, which credentials work, and step-by-step setup with gcloud or Terraform.