Australian cloud for business software — built and run in Sydney since 2003

NetLeverage
NetLeverage

S3 Credentials for Automated Delivery: Least Privilege and Rotation

Technical article
Cloud

Direct answer: A delivery job that only writes files to one place should hold a credential that can only write to that place.

  1. List what the job really calls. Usually that is uploading objects, including multipart uploads, and sometimes reading back metadata to confirm the upload.
  2. Grant exactly those actions. Scope them to the bucket and key prefix the job writes to. Leave out delete and permission-changing actions. Check the bucket policy too, because allows there add to the job's own.
  3. Prefer temporary credentials from an IAM role where the job can obtain them.
  4. If you must keep a long-term access key, rotate it the way AWS documents. Create a second key while the first is still active. Move the job to the new key. Check the old key's last-used information. Deactivate the old key, confirm the job still works, and delete it only after a waiting period. Deactivation is the rollback step: a job you missed fails visibly, and you can reactivate the key while you fix it.

Why it matters

The AWS IAM User Guide says access keys "are long-term credentials". "IAM users with access keys are an account security risk". The recommended practice is to use temporary credentials, such as IAM roles, instead of creating long-term access keys. Temporary credentials expire after a short period; long-term keys "remain valid until you manually revoke them".

A delivery credential is a typical long-term key that drifts into risk:

  • It is stored next to the job, often in a configuration file or the shared AWS credentials file, which the IAM User Guide notes stores credentials in plaintext.
  • It is broad, created in a hurry with a managed policy allowing all of S3 or the whole account.
  • It is old. Nobody remembers which jobs use it, so nobody rotates it.
  • It can destroy the target. If it can delete objects or change bucket policy, a leaked delivery key can remove the very backups or exports it was created to deliver.

Over-permission sets what a leaked key can do; careless rotation causes a failed delivery nobody notices until the file is needed.

How it works

Who may do what: the evaluation rules you need

S3 access in AWS is decided by policies:

  • Identity-based policies are attached to the IAM user or role the job uses.
  • Resource-based policies are bucket policies, which only the bucket owner can attach.

The IAM policy evaluation logic says that, within one account, a request is allowed if an identity-based policy, a resource-based policy or both allow it. An explicit deny in either overrides the allow. Anything not allowed is denied by default.

Two consequences matter for delivery credentials:

  • Every allow counts. Identity and bucket-policy allows combine, so narrowing the job's own policy does not remove a broader allow elsewhere. A bucket-policy statement that names the job's principal (or everyone), or an ACL grant where ACLs are enabled, can still permit writes outside the prefix or deletes. The effective permission is the whole set of applicable policies, so inspect all of them (Checks 2 and 4). A carefully scoped explicit deny in the bucket policy is a backstop that holds even if someone later adds a broader allow.
  • Deny wins. A deny in the bucket policy (for example, refusing requests that do not use TLS) applies to the job whatever its own policy says.

Object Ownership defaults to Bucket owner enforced for new buckets: ACLs are disabled, the bucket owner owns every object, and only policies control access. The Amazon S3 User Guide recommends keeping ACLs disabled unless per-object control is needed.

What a write-only delivery job actually needs

The Amazon S3 User Guide's multipart upload page lists the permission for each step:

Step Permission needed
Create (initiate) a multipart upload s3:PutObject on the object
Upload each part s3:PutObject on the object
Complete the multipart upload s3:PutObject on the object
Stop (abort) a multipart upload s3:AbortMultipartUpload
List the parts of an upload s3:ListMultipartUploadParts
List uploads in progress in a bucket s3:ListBucketMultipartUploads on the bucket

The core grant is small. s3:PutObject covers single-request uploads and every step of a multipart upload. The other three actions are needed only if the tool aborts failed uploads, resumes by listing parts, or lists unfinished uploads; check its documentation. A tool that aborts failed uploads without s3:AbortMultipartUpload leaves the failed parts behind. The article on interrupted large uploads, listed under Related articles, covers cleaning those up.

Some extras are optional and come with conditions.

  • Reading back to confirm. HeadObject (reading an object's metadata, for example to confirm size or checksum after upload) needs s3:GetObject. The Amazon S3 API Reference says a missing object returns 404 Not Found only when the caller also has s3:ListBucket, otherwise 403 Forbidden. Without s3:ListBucket, read "access denied" as "not there or not allowed", not as proof of a permission fault.
  • Listing. If the job lists objects, s3:ListBucket can be restricted to the job's prefix with the s3:prefix condition key. The Amazon S3 User Guide shows this pattern.
  • Encryption with a KMS key. If the bucket uses SSE-KMS, the multipart page says the requester also needs kms:GenerateDataKey (for CreateMultipartUpload) and kms:Decrypt (for UploadPart and UploadPartCopy) on that key. It also says to validate the permissions in both the KMS key policy and the IAM policy. Two documented outcomes differ when kms:Decrypt is missing. The multipart page says an object completed through CompleteMultipartUpload is then created without a checksum value. The CompleteMultipartUpload API reference says that when the upload carries an additional checksum value and the object is KMS-encrypted, kms:Decrypt is required for the completion request to succeed. Keep three cases apart: a completion that failed, a completed object with no checksum to check, and a completion whose checksum you verified. Grant the missing permission; never turn off the client's integrity checks to get past it.
  • Headers on the upload. The PutObject reference lists extra permissions that apply only when the upload request carries extra headers. For example, s3:PutObjectTagging if the job sets tags. With ACLs disabled, the job should not set ACLs.

A delivery job normally does not need s3:DeleteObject, s3:DeleteObjectVersion, s3:PutBucketPolicy, s3:PutLifecycleConfiguration or any iam:* action.

Overwrite is still a write

s3:PutObject lets the job write any key under its prefix, including keys that already exist. On a bucket without versioning, a leaked write-only key can still overwrite earlier deliveries. Two documented controls limit that:

  • S3 Versioning. It is disabled by default and must be enabled explicitly. When on, an overwrite creates a new version and the previous one stays restorable; a delete adds a delete marker. Noncurrent-version lifecycle rules then stop storage growing.
  • Conditional writes. A bucket policy can require the If-None-Match header on PutObject and CompleteMultipartUpload through the s3:if-none-match condition key. Writes then succeed only when the key does not already exist. For multipart uploads, the policy must exempt CreateMultipartUpload, UploadPart and UploadPartCopy with the s3:ObjectCreationOperation condition key, because those calls do not accept the header. Enforcing it also stops copy operations into that bucket or prefix, so use it only if the job writes each key once and never copies there.

Conditions that narrow a long-term key further

The IAM User Guide documents inline policies that limit an IAM user's access keys:

  • Time-bound: a Deny on all actions when aws:CurrentTime is after a set date.
  • Source address: a Deny unless aws:SourceIp is within listed ranges. The addresses must not be hidden by a VPN or proxy, and aws:ViaAWSService must be handled so AWS services acting for the user are not blocked.

For S3, the Amazon S3 User Guide shows denying requests where aws:SecureTransport is false (no TLS), and using s3:TlsVersion to require a minimum TLS version. It warns that for service-to-service calls some network context, including aws:SecureTransport and aws:SourceIp, is redacted. Deny statements using them should therefore exclude AWS service principals with aws:PrincipalIsAWSService. The s3:x-amz-server-side-encryption condition key can require a particular server-side encryption type on uploads.

Temporary credentials instead of a stored key

The IAM best practices say workloads should use temporary credentials with IAM roles: inside AWS, an instance or task role. Outside AWS, IAM Roles Anywhere lets servers and applications obtain temporary credentials by presenting X.509 certificates issued by a CA you register as a trust anchor. That replaces a stored access key with a certificate you manage, if the delivery tool and your PKI support it. The rest of this article assumes you may still hold a long-term key.

What IAM tells you about key use

  • Per key: aws iam get-access-key-last-used returns the date, service and Region where a key was last used. The CLI reference notes that the date is null, and service and Region show "N/A", when the key has not been used since IAM began tracking. Treat "N/A" as "no recorded use", not as proof of no use outside what IAM records.
  • Per service and action: IAM last accessed information shows the last time an identity used each service, and for Amazon S3 individual management actions, with tracking for S3 actions from 12 April 2020. Recent activity may take up to four hours to appear. The guide says action-level information is not available for any data-plane event, so object operations such as PutObject and GetObject never appear there. An entry does not mean success either: the request may have been denied, and the guide names CloudTrail as the authoritative record.
  • Per call: AWS CloudTrail records the calls themselves, and the IAM User Guide recommends it for monitoring key usage. For S3 object requests this holds only if data-event logging was set up. The Amazon S3 User Guide says CloudTrail records only management events by default, data events need a trail configured for them, data events are not shown in CloudTrail event history, and additional charges apply.
  • Key limit: an IAM user can have at most two access keys. That limit is why rotation is a choreography and not a free-for-all.

Read-only checks

None of these was run for this article. They only read. Run them from an administrative identity, not the delivery credential. Do not print, paste or store secret access keys. Access key IDs are identifiers, but keep them out of public tickets anyway.

1. Which identity does the job use, and which keys does it have?

# Read-only. Lists the user's access keys (IDs, status, creation date). Never shows secrets.
aws iam list-access-keys --user-name delivery-job-example
# Read-only. Last use of one key.
aws iam get-access-key-last-used --access-key-id <key-id-from-the-list>

Note each key's status, age and last use (when, Region, service). An unexpected Region or service is investigated before anything else.

2. What can that identity do now?

# Read-only. Policies attached to and inline in the user, and groups it belongs to.
aws iam list-attached-user-policies --user-name delivery-job-example
aws iam list-user-policies --user-name delivery-job-example
aws iam list-groups-for-user --user-name delivery-job-example

Read each policy document, group policies included (aws iam get-policy-version for managed, aws iam get-user-policy for inline). Look for "Action": "s3:*", "Resource": "*", delete or bucket-configuration actions, and anything outside S3.

3. What has it actually used?

Two sources answer different parts of this question.

  • Services and management actions: The user's Last accessed tab in the IAM console shows which services, and which S3 management (bucket-level) actions, the identity has called. It helps remove services and bucket-configuration actions the job never touches. It cannot show which object actions the job needs, because object operations are not in it.
  • Object operations: Use the delivery tool's documentation for the calls it makes on upload, resume, read-back and failure clean-up. Where they are captured, add CloudTrail S3 data events for the bucket. First confirm the capture exists: a trail whose data-event selectors cover this bucket and prefix, a known log destination, and a window that includes representative runs, failed uploads, clean-up and the least frequent schedule. Query that log destination, not CloudTrail event history. If no data events were captured, there is no history to consult. Record that gap, then rely on the documentation or enable data-event logging for a reviewed period (it is charged) before narrowing.

Record each call's error code. A denied attempt shows the job wants the action, not that it ever succeeded. An action absent from the evidence is unobserved, not proven unused.

4. What does the bucket allow and refuse?

# Read-only. Bucket policy, ownership, versioning and encryption settings.
aws s3api get-bucket-policy --bucket example-delivery-bucket
aws s3api get-bucket-ownership-controls --bucket example-delivery-bucket
aws s3api get-bucket-versioning --bucket example-delivery-bucket
aws s3api get-bucket-encryption --bucket example-delivery-bucket
# Only if ACLs are enabled. Grants on the bucket.
aws s3api get-bucket-acl --bucket example-delivery-bucket

Each of these needs the corresponding read permission on the bucket. Note every Allow statement whose principal is the job's identity, its account or everyone: those allows add to the identity policy, so the job may be able to do more than its own policy says. Note any deny statements (TLS, encryption, conditional writes), whether ACLs are disabled (if not, note grants to the job), whether versioning is on, and whether SSE-KMS is in use. If it is, read the key policy too (aws kms get-key-policy --key-id <key-id> --policy-name default). The job needs the KMS permissions described above in both the key policy and its IAM policy.

5. Where is the secret stored, and who can read it?

On the job host, identify how the job obtains its credentials (environment variables, a credentials file, a secrets manager or a role), and which accounts can read them, without opening or printing the secret. Every copy must be updated during rotation and removed afterwards.

Interpreting the results

What you find What it means Next step
Policy grants s3:* or * on * Over-permissioned; a leak exposes everything Decision 1
Delete or bucket-configuration actions granted A leaked key can destroy deliveries or change protection Decision 1; consider versioning (Decision 3)
Two Active keys, one with no recent use A previous rotation never finished Decision 2 from step 4 (deactivate the unused key)
Bucket policy or ACL grants the job's principal (or everyone) more The identity policy is not the effective limit Decision 1, including that statement
Key last used from an unexpected Region or service Possible misuse or an unknown consumer Investigate with CloudTrail before rotating (data events only if captured, Check 3); treat as an incident if unexplained
Last-used "N/A" on an old key No recorded use since tracking began Deactivate first (Decision 2, step 4), never delete straight away
Job sees 403 on HeadObject for files it just uploaded Missing s3:GetObject, a missing object without s3:ListBucket, or a KMS/encryption condition Check the upload result and the policy before widening anything
Uploads fail only for large files Missing KMS permissions or multipart-related actions, or a bucket condition that blocks part uploads Compare with the permission table; check the bucket policy's conditions
Key in plaintext on several hosts Each copy is an exposure and a rotation step Reduce copies; consider a secrets manager or role (Decision 4)

Decision guidance

Change IAM and bucket policies under change control, saving the current documents first. A mistake can stop deliveries, or lock out administrators if applied to the wrong principal.

Decision 1: Replace a broad policy with a scoped one

Write a policy for the job's identity that allows only the actions you confirmed, on the job's own prefix. As a shape (example bucket and prefix; adjust to what Check 3 established). It is one grant, not the job's effective boundary:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "WriteDeliveriesUnderOwnPrefix",
      "Effect": "Allow",
      "Action": ["s3:PutObject", "s3:AbortMultipartUpload", "s3:ListMultipartUploadParts"],
      "Resource": "arn:aws:s3:::example-delivery-bucket/deliveries/site-a/*"
    }
  ]
}

Add s3:GetObject on the same prefix only if the job reads back. Add s3:ListBucket on the bucket ARN, with an s3:prefix condition, only if the job lists. Add KMS actions on the specific key only if the bucket uses SSE-KMS, and confirm the key policy allows them too. Attach the new policy and run the job once before detaching the old broad policy. While both are attached the job still has the broad rights, so this step proves nothing about the scope. Then detach the old policy and run the job again. If Check 4 found a bucket-policy allow or ACL grant that gives the job broader rights, constrain or remove it through the bucket owner's change process. Otherwise the narrow identity policy changes nothing.

Validate the new document with IAM Access Analyzer if available, as the IAM best practices recommend.

  • Verification: Test both sides against the final set of identity, bucket and key policies. The next scheduled delivery succeeds, including any abort or list-parts step you granted. The objects appear under the prefix (the published article on verifying a delivered backup covers how to check them). An attempt with the job's credential to delete an object, or to write outside the prefix, is refused. Use a test object or prefix, never a real delivery.
  • Rollback: Re-attach the saved broad policy. Then find the missing action from the client's error and, if S3 data events are captured (Check 3), from the denied entry in that log. Add only that action.

Decision 2: Rotate a long-term access key without an outage

This follows the AWS procedure:

  1. Check the slot. The user must have only one key. If there are two, first finish or undo the earlier rotation (steps 4–6 for the unused key).
  2. Create the second key while the first is still active. It is active immediately. The secret is shown only at creation: store it directly in the job's secret store, never in tickets, email or chat. Tag the key with a description.
  3. Update every consumer of the key found in Check 5. Run the job once.
  4. Check the old key's last-used information (Check 1). AWS suggests waiting several days and checking again. Even if it shows no use, deactivate the old key rather than deleting it.
  5. Use only the new key for a full schedule cycle. Anything still using the old key now fails. That is how you find it. Reactivate the old key if needed, update that consumer, and return to step 3.
  6. Delete the old key after a waiting period long enough to cover the job's least frequent schedule. Then remove the old secret from every place it was stored.
  • Verification: Last-used for the new key shows recent S3 use. Last-used for the old key stops advancing after step 3. The next scheduled deliveries succeed while the old key is inactive.
  • Rollback: Until step 6, set the old key back to Active (aws iam update-access-key --status Active). After step 6 there is no rollback for the old key. Issue a new one through steps 2–3.

If a key may have been exposed, the order changes. Contain first: deactivate the exposed key promptly even if that causes a delivery failure. Review CloudTrail for its use: management events, plus S3 data events if they were captured. If they were not, record that object-level use of the key cannot be established. Then issue a replacement. The access-revocation article listed under Related articles covers this in the context of a departed administrator.

Decision 3: Protect earlier deliveries from overwrite or deletion

Removing delete actions from the job only addresses the job's own key. To protect deliveries against any write through that prefix, enable S3 Versioning on the bucket. Versioning keeps earlier versions recoverable, but it is not immutable retention: a principal allowed to delete versions can still remove them, lifecycle rules expire noncurrent versions, and versioning can be suspended. Add noncurrent-version lifecycle rules that match your retention policy, so old versions do not accumulate without limit. Where the job writes each key exactly once, consider a bucket policy that enforces conditional writes with s3:if-none-match, including the multipart exemption described above. These bucket-wide decisions affect every bucket user, so agree them with the bucket owner.

  • Verification: get-bucket-versioning shows Enabled. A test overwrite of a test key creates a second version. With conditional writes enforced, an upload to an existing test key fails and a new key succeeds, including through multipart.
  • Rollback: Versioning cannot be turned off once enabled, only suspended. Existing versions stay until lifecycle rules or deletes remove them. Plan for that before enabling it. Removing the conditional-write statement restores ordinary overwrites.

Decision 4: Move from a stored key to temporary credentials

Inside AWS, give the job a role. Elsewhere, if your tooling supports it, evaluate IAM Roles Anywhere with certificates from your CA, a larger change with its own certificate lifecycle. Pilot it on one job, then remove the IAM user's access keys.

  • Verification: Where S3 data events are captured (Check 3), the job's object requests show the role session, not the IAM user. Without them, confirm the credential source from the client's own log. The user has no active access keys.
  • Rollback: Keep the old access key deactivated, not deleted, during the pilot, and reactivate it if needed.

What not to do

  • Do not give delivery jobs AdministratorAccess, AmazonS3FullAccess or s3:* "to make it work". Find the missing action instead.
  • Do not delete an old key the moment the new one works. Deactivate, wait, then delete.
  • Do not reuse one key across many jobs or sites. Rotation and incidents then hit all of them, and last-used evidence cannot tell them apart.
  • Do not create access keys for the root user. The IAM User Guide says not to.
  • Do not embed keys in scripts, images or source repositories. Do not paste secrets into tickets or chat.
  • Do not assume an S3-compatible service supports the same actions, condition keys, last-used data or key limits. Check its documentation.

Limitations

  • AWS only: The article describes Amazon S3 general purpose buckets and AWS IAM. Directory buckets, S3 Access Points, VPC endpoint policies and AWS Organizations controls can change the outcome and are not covered in detail.
  • S3-compatible services: NAS appliances, other clouds and self-hosted stores often implement a subset of the policy language and their own key management. Check the provider's documentation.
  • Service authorisation reference: The AWS service authorisation reference page for Amazon S3 actions could not be retrieved for this article. Action names were confirmed from the Amazon S3 User Guide and API Reference instead.
  • CloudTrail evidence: Object-level history exists only for periods when S3 data-event logging was configured for the bucket. Nothing here can recover calls made before that.
  • No lab testing: None of the commands or policies was run for this article.

Acceptance checklist

  • [ ] The job's identity, keys, key ages and last use are recorded (Check 1).
  • [ ] The job's object actions are established from its documentation and, where captured, S3 data events over representative runs; services and management actions from last-accessed data; evidence gaps are recorded (Check 3).
  • [ ] Bucket-policy allows, any ACL grants and the KMS key policy that apply to the job were reviewed with its identity policies (Checks 2 and 4).
  • [ ] The job's policy allows only those actions on its own prefix; delete and configuration actions are absent (Decision 1).
  • [ ] After the broad policy was detached, the next scheduled delivery succeeded and the prohibited test actions were refused.
  • [ ] The rotation used two keys, deactivation before deletion and a waiting period, and every stored copy of the old secret was removed (Decision 2).
  • [ ] Protection for earlier deliveries (versioning or conditional writes) was agreed with the bucket owner (Decision 3).
  • [ ] Moving to temporary credentials was considered, with the reason recorded if it was not done (Decision 4).

References

All accessed 2 November 2026.

  • AWS, IAM User Guide, "Manage access keys for IAM users": access keys are long-term credentials; temporary credentials preferred; two keys per user maximum; secret retrievable only at creation; do not create root access keys; credentials file stored in plaintext; CloudTrail monitoring. https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
  • AWS, IAM User Guide, "Update access keys": create second key while first active, update applications, check last used, wait several days, deactivate before deleting, reactivate if something breaks, Access key age column. https://docs.aws.amazon.com/IAM/latest/UserGuide/id-credentials-access-keys-update.html
  • AWS, IAM User Guide, "Secure access keys": do not embed keys; temporary security credentials expire, long-term keys remain valid until revoked. https://docs.aws.amazon.com/IAM/latest/UserGuide/securing_access-keys.html
  • AWS, IAM User Guide, "Control the use of access keys by attaching an inline policy to an IAM user": time-bound (aws:CurrentTime) and source-IP (aws:SourceIp, aws:ViaAWSService) deny policies. https://docs.aws.amazon.com/IAM/latest/UserGuide/access-keys_inline-policy.html
  • AWS, IAM User Guide, "Security best practices in IAM": temporary credentials for workloads, least privilege, last accessed information, conditions, IAM Access Analyzer policy validation. https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html
  • AWS, IAM User Guide, "Policy evaluation logic": explicit deny overrides allows; identity and resource policies within an account. https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
  • AWS, IAM User Guide, "Refine permissions in AWS using last accessed information": S3 action-level tracking since 12 April 2020; data appears within four hours; action information not available for any data-plane event; entries may be denied requests, CloudTrail authoritative. https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_access-advisor.html
  • AWS, IAM User Guide, "AWS global condition context keys": aws:SecureTransport and other global keys. https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html
  • AWS CLI Command Reference, "get-access-key-last-used": output fields and "N/A"/null meaning. https://docs.aws.amazon.com/cli/latest/reference/iam/get-access-key-last-used.html
  • AWS, IAM Roles Anywhere User Guide, "What is AWS Identity and Access Management Roles Anywhere?": temporary credentials for workloads outside AWS using X.509 certificates and trust anchors. https://docs.aws.amazon.com/rolesanywhere/latest/userguide/introduction.html
  • AWS, Amazon S3 User Guide, "Uploading and copying objects using multipart upload": per-step permissions, KMS permissions for multipart in key and IAM policies, checksum without kms:Decrypt. https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html
  • AWS, Amazon S3 User Guide, "Bucket policy examples using condition keys": s3:prefix, s3:x-amz-server-side-encryption, s3:TlsVersion, aws:SecureTransport with aws:PrincipalIsAWSService. https://docs.aws.amazon.com/AmazonS3/latest/userguide/amazon-s3-policy-keys.html
  • AWS, Amazon S3 User Guide, "Controlling ownership of objects and disabling ACLs": Bucket owner enforced default, ACLs disabled, policy-only access. https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html
  • AWS, Amazon S3 User Guide, "Enforce conditional writes on Amazon S3 buckets": s3:if-none-match/s3:if-match, s3:ObjectCreationOperation for multipart, copy limitation. https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes-enforce.html
  • AWS, Amazon S3 User Guide, "Retaining multiple versions of objects with S3 Versioning": disabled by default, overwrite creates new version, delete markers, noncurrent expiration. https://docs.aws.amazon.com/AmazonS3/latest/userguide/Versioning.html
  • AWS, Amazon S3 User Guide, "Enabling CloudTrail event logging for S3 buckets and objects": data events need a trail, CloudTrail records management events only by default, data events not in event history, additional charges. https://docs.aws.amazon.com/AmazonS3/latest/userguide/enable-cloudtrail-logging-for-s3.html
  • AWS, Amazon S3 API Reference, "CompleteMultipartUpload": with an additional checksum on a KMS-encrypted object, kms:Decrypt is required for completion to succeed. https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html
  • AWS, Amazon S3 API Reference, "HeadObject": requires s3:GetObject; 404 versus 403 depends on s3:ListBucket. https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html
  • AWS, Amazon S3 API Reference, "PutObject": s3:PutObject always required; extra permissions for ACL and tagging headers. https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html

Related articles

Learning notes

  1. s3:PutObject covers ordinary uploads and every step of a multipart upload. Abort and list-parts actions are separate and optional.
  2. Allows from identity and bucket policies combine, and an explicit deny overrides any allow. Check both kinds of policy: the job's own narrow grant is not its effective limit.
  3. Write-only still means "can overwrite". Versioning or enforced conditional writes protect earlier deliveries.
  4. Rotate with two keys: create, switch, check last use, deactivate, wait, delete. Deactivation is the rollback point.
  5. Temporary credentials (roles, or IAM Roles Anywhere outside AWS) remove the long-term AWS access key, and are AWS's recommended practice for workloads. Roles Anywhere replaces it with a certificate whose lifecycle you manage.
  6. IAM last-accessed data never shows object operations. S3 data events do, but only if logging was set up before the period you review.