Gonzalo Arce
09/02/2025, 11:41 AMassume_role_policy = jsonencode(
{
Statement = [
{
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"api.prefect.cloud/oidc-provider:aud" = "prefect-cloud"
"api.prefect.cloud/oidc-provider:sub" = "prefect:cloud:[REDACTED_PREFECT_ACCOUNT_ID]"
}
}
Effect = "Allow"
Principal = {
Federated = "arn:aws:iam::[REDACTED_AWS_ACCOUNT_ID]:oidc-provider/api.prefect.cloud/oidc-provider"
}
},
]
Version = "2012-10-17"
}
)
however the flow keeps failing with:
Flow run could not be submitted to infrastructure: An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity
Marvin
09/02/2025, 11:41 AMMarvin
09/02/2025, 11:46 AM// Trust relationship for Prefect Cloud OIDC
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = "sts:AssumeRoleWithWebIdentity",
Principal = {
Federated = "arn:aws:iam::[REDACTED_AWS_ACCOUNT_ID]:oidc-provider/api.prefect.cloud/oidc"
},
Condition = {
StringEquals = {
"api.prefect.cloud/oidc:aud" = "prefect-cloud"
},
StringLike = {
// Start with your account id and add a wildcard; if you know the workspace id, you can target it more narrowly, e.g. "prefect:cloud:[ACCOUNT_ID]:[WORKSPACE_ID]:*"
"api.prefect.cloud/oidc:sub" = "prefect:cloud:[REDACTED_PREFECT_ACCOUNT_ID]:*"
}
}
}
]
})
Common causes of this AccessDenied
- The OIDC provider issuer in AWS does not exactly match https://api.prefect.cloud/oidc (no trailing slash, no extra “oidc-provider” suffix).
- The Principal.Federated ARN points to the wrong provider path.
- The Condition keys use the wrong prefix (must be api.prefect.cloud/oidc).
- The sub claim is too strict (StringEquals) and does not match the actual token subject. Using StringLike with a wildcard generally resolves this; you can then tighten it once you confirm the exact sub form for your workspace.
- System clock skew (rare, but tokens are time-bound).
- The role being assumed lacks permissions to perform the AWS actions you need post-assume (separate from the trust relationship). The AccessDenied you’re seeing is happening at assume time, though, which points at the trust relationship/conditions.
A couple quick questions to ensure the rest of your setup is aligned
- Which work pool/worker type are you using to submit to AWS (ECS, Batch, Kubernetes, etc.)?
- How did you configure AWS credentials for the worker/deployment? Are you using Prefect Cloud OIDC directly or a credentials block/env vars?
- In AWS IAM, can you confirm the OIDC provider you created shows “Provider URL” = https://api.prefect.cloud/oidc and that your role’s trust policy references that exact provider ARN?
If you can share a redacted copy of your AWS OIDC provider definition (the Provider URL as shown in AWS) and your current role trust policy after the changes above, I can sanity-check it further.Gonzalo Arce
09/02/2025, 11:51 AM/oidc-provider
your info is wrong, as It added successfully on AWS with that and @Kevin Grismore previously provided me with that detail.
But I think the trust policy is wrong as in , prefect not sending what the policy expects in terms of audience or condition / subMarvin
09/02/2025, 11:51 AMMarvin
09/02/2025, 11:52 AMassume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = "sts:AssumeRoleWithWebIdentity",
Principal = {
Federated = "arn:aws:iam::[REDACTED_AWS_ACCOUNT_ID]:oidc-provider/api.prefect.cloud/oidc-provider"
},
Condition = {
StringEquals = {
"api.prefect.cloud/oidc-provider:aud" = "<http://sts.amazonaws.com|sts.amazonaws.com>"
},
StringLike = {
// Start broader to validate, then tighten to your workspace
"api.prefect.cloud/oidc-provider:sub" = "prefect:cloud:[REDACTED_PREFECT_ACCOUNT_ID]:*"
// Once you confirm the workspace id:
// "api.prefect.cloud/oidc-provider:sub" = "prefect:cloud:[ACCOUNT_ID]:[WORKSPACE_ID]:*"
}
}
}
]
})
How to validate quickly
- First, add sts.amazonaws.com to the IAM identity provider’s Audiences and switch the trust policy aud to sts.amazonaws.com.
- Temporarily use "prefect☁️[ACCOUNT_ID]:*" for sub to confirm assume now succeeds. If it does, tighten to "prefect☁️[ACCOUNT_ID][WORKSPACE ID]*".
- If it still fails, check CloudTrail for the failed sts:AssumeRoleWithWebIdentity event — it often hints if the audience or subject didn’t match.
If you can share:
- What “Audience(s)” you currently have configured on the IAM identity provider
- Your Prefect workspace id (redacted is fine, just structure)
I can give you an exact, tightened sub pattern to use.