Permissions for publishing
Let the deploy project write to your website bucket, and check that the pipeline can start both builds.
About 15 min · Verified 8 October 2026
Three different identities touch your website, and each needs a different permission. Mixing them up is the most common reason the first deploy fails.
| Identity | Needs | Where it is granted |
|---|---|---|
| Anyone on the internet | Read files (s3:GetObject) | The bucket policy (guide 1, chapter 8) |
The shortlink-web-deploy project's role | List, write and delete objects in your bucket | An inline policy on that role (this chapter) |
| The pipeline's service role | Start both CodeBuild projects | The pipeline role (checked here) |
Find the role name#
Look up the deploy project's service role#
aws codebuild batch-get-projects --region ap-south-1 --names shortlink-web-deploy \
--query 'projects[0].serviceRole' --output textThe last part of the ARN is the role name, normally codebuild-shortlink-web-deploy-service-role.
Let it write to the bucket#
Add the inline policy#
Open IAMRolescodebuild-shortlink-web-deploy-service-rolePermissionsAdd permissionsCreate inline policyJSON. Name it shortlink-web-deploy-website-sync.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::<WEB_BUCKET>"
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::<WEB_BUCKET>/*"
}
]
}Replace <WEB_BUCKET> with your own value (or fill in the known ones once under My values at the top of the page).
Two statements are needed because ListBucket applies to the bucket ARN (…:bucket), while the object actions apply to the objects (…:bucket/*). aws s3 sync lists first to work out what changed, and --delete needs DeleteObject. Without the first statement you get a confusing AccessDenied on ListObjectsV2.
Check the role can also read the pipeline artifact#
The role that the wizard created for this project normally includes read access to the codepipeline-<region>-… bucket. Verify:
aws iam list-attached-role-policies --role-name codebuild-shortlink-web-deploy-service-role --output table
aws iam list-role-policies --role-name codebuild-shortlink-web-deploy-service-role --output tableCodeBuildBasePolicy-shortlink-web-deploy-<region> (logs and artifact bucket), and your inline shortlink-web-deploy-website-sync.Deploy fails with AccessDenied on the artifact bucket
Add this inline policy to the same role, naming it shortlink-web-deploy-artifacts-read:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:GetObjectVersion", "s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::<ARTIFACT_BUCKET>", "arn:aws:s3:::<ARTIFACT_BUCKET>/*"]
}
]
}Replace <ARTIFACT_BUCKET> with your own value (or fill in the known ones once under My values at the top of the page).
Find the bucket with aws codepipeline get-pipeline --name shortlink-web-prod --query pipeline.artifactStore.location --output text.
Let the pipeline start both builds#
Add an inline policy to the pipeline role#
The wizard grants codebuild:StartBuild for the project you created in it. When you added the second project in the editor the console may not have extended the policy. If the pipeline role cannot start a project, the action fails in CodePipeline before any CodeBuild log exists, which is confusing. Adding this is harmless if it is already allowed.
Find the role: aws codepipeline get-pipeline --region ap-south-1 --name shortlink-web-prod --query pipeline.roleArn --output text. Then IAMRoles(that role)PermissionsAdd permissionsCreate inline policyJSON, name shortlink-web-start-builds:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["codebuild:StartBuild", "codebuild:BatchGetBuilds"],
"Resource": [
"arn:aws:codebuild:ap-south-1:<AWS_ACCOUNT_ID>:project/shortlink-web-build",
"arn:aws:codebuild:ap-south-1:<AWS_ACCOUNT_ID>:project/shortlink-web-deploy"
]
}
]
}Replace <AWS_ACCOUNT_ID> with your own value (or fill in the known ones once under My values at the top of the page).
What each failure means#
| Error text | Identity to fix |
|---|---|
AccessDenied on s3:ListBucket, PutObject or DeleteObject in the WebDeploy log | codebuild-shortlink-web-deploy-service-role |
not authorized to perform: codebuild:StartBuild with no CodeBuild log | The pipeline service role |
| The site returns 403 after a successful deploy | The bucket policy (public read), not the roles |
AccessDenied listing a bucket you do not own | The buildspec still points at someone else's bucket. Redo the previous chapter |
Next: run the first release.
Found a mistake? Edit this page on GitHub.