AWS Assume Role for S3 Destinations

Let WCH upload your published project.zip into your own Amazon S3 bucket using short-lived credentials, so you never have to store a permanent AWS key in WCH.

When you publish a project, WCH can deliver your built project.zip straight into an S3 bucket you own. There are two ways to grant WCH access to that bucket:

  • Access Key: you paste a long-lived AWS access key and secret into WCH.
  • Assume Role: you create a role in your own AWS account and grant WCH permission to assume it. WCH then requests temporary, one-hour credentials each time it publishes.

Assume Role is the recommended option. It follows AWS security best practice: no static secret is stored, access is scoped to exactly what the role allows, and you can revoke WCH's access at any time by editing or deleting the role.

The WCH principal that assumes your role

WCH uses a single AWS identity to request access to your bucket. This is the identity you will trust in your role. You do not need any credentials from WCH; you only grant this principal permission to assume a role you create. Ask the WCH team for the following values:

  • AWS Account ID
  • IAM User Name
  • IAM User ARN

Step 1: Create the role in your AWS account

  1. Sign in to the AWS Console for the account that owns your S3 bucket.
  2. Go to IAM, then Roles, then Create role.
  3. For Trusted entity type, choose Custom trust policy.
  4. Paste the trust policy from Step 2.
  5. On the next screen, attach the permissions policy from Step 3.
  6. Name the role, for example wch-s3-upload, and create it.
  7. Copy the finished role's ARN. It looks like arn:aws:iam::123456789012:role/wch-s3-upload. You will paste this into WCH in Step 4.

Step 2: Set the trust policy

The trust policy tells your role who is allowed to assume it. It must name the WCH identity as the trusted principal.

Recommended: with an External ID

An External ID is a shared secret that protects against your role being assumed on someone else's behalf. Choose any hard-to-guess value (a UUID works well), use it here, and enter the same value in WCH.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:user/wes-assume-role"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "your-chosen-external-id"
        }
      }
    }
  ]
}

Without an External ID

The External ID is optional. If you leave it out, remove the Condition block:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:user/wes-assume-role"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Use an External ID whenever you can. Without it, any project that could get the WCH identity to assume your role ARN could reach your bucket. The External ID makes sure the role is only assumed on your behalf.

Step 3: Grant S3 upload permissions

The role also needs a permissions policy describing what it may do once assumed. WCH only needs to upload the zip. Larger files use a multipart upload, so the abort action is included for cleanup:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:AbortMultipartUpload"
      ],
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}
  • Replace your-bucket-name with your actual bucket name.
  • The /* scopes the permission to objects inside the bucket.
  • To restrict WCH to one folder, narrow the resource, for example arn:aws:s3:::your-bucket-name/releases/*.

Step 4: Connect the destination in WCH

  1. Open your project in WCH.
  2. Open the AWS destination settings and add a new destination.
  3. Set Authentication Type to Assume Role.
  4. Fill in the fields described below.
  5. Save the destination.

The fields you will complete:

  • Role ARN: the ARN of the role you created, for example arn:aws:iam::123456789012:role/wch-s3-upload.
  • External ID (Optional): the exact External ID you used in the trust policy. Leave blank if you did not use one.
  • Region: the AWS region of your bucket, for example us-east-1.
  • Bucket Name: your S3 bucket name, with no s3:// prefix.
  • File Name: the object name to write, for example project.zip. Tick Use project name to name the file after your project automatically.
  • Is Production?: turn on if this is your production target. Only one production destination is allowed per project.

What happens when you publish

  1. WCH builds and zips your project into project.zip.
  2. WCH assumes your role using the WCH identity (arn:aws:iam::123456789012:user/wes-assume-role), passing your External ID if one is configured.
  3. AWS returns temporary credentials that expire after one hour.
  4. WCH uses those credentials to upload the zip to your bucket, in the region and under the file name you chose.

Because the credentials are temporary and scoped to the role, WCH never stores a permanent key to your account.

Troubleshooting

  • Access denied when assuming the role: the trust policy does not name arn:aws:iam::985542660797:user/wes-assume-role, or the External ID in WCH does not exactly match the one in the trust policy.
  • Assume role works, but the upload fails: the role's permissions policy does not allow s3:PutObject on your bucket, or the resource path does not match.
  • Wrong region error: the Region in WCH does not match where the bucket actually lives.
  • File never appears: check that the File Name and any folder prefix in the permissions policy line up with where you are looking.

Revoking WCH's access

Because access flows entirely through the role you created, you stay in control:

  • Pause access: edit the trust policy to remove the WCH principal.
  • Rotate the secret: change the External ID in both the trust policy and WCH.
  • Remove access entirely: delete the role, or delete the destination in WCH.