Security · Topic 2 of 6

Permissions, Access Control and Presigned URLs

Write IAM identity and resource policies, apply fine grained conditions and MFA, and hand out time limited access with S3 and CloudFront presigned URLs.

  • 5 min
In a nutshell
  • Default deny, explicit deny wins, and cross account access needs an allow on both sides.
  • Resource policies have a Principal. Identity policies do not.
  • Permissions boundaries and SCPs limit permissions and never grant them.

What it is

Permissions decide what an authenticated principal may do. A developer writes them in two places: identity based policies attached to a user or role, and resource based policies attached to a resource such as an S3 bucket, an SQS queue, a Lambda function or a KMS key.

Access control also covers the extra checks you add: conditions, tags, MFA, and temporary links such as presigned URLs.

Requestprincipal, action, resourceevaluated againstPoliciesidentity, resource, boundary, SCPresultDecisionexplicit deny, else allow, else default deny

How it works

Policy evaluation

Every request is denied by default. An explicit Deny in any applicable policy always wins. Otherwise an Allow is needed.

Within one account, an allow in either the identity policy or the resource policy is enough. Across accounts, both sides must allow the action. Permissions boundaries, service control policies and session policies only limit; they never grant on their own.

PolicyAttached toTypical use
Identity policyUser, group, roleWhat this principal may do
Resource policyBucket, queue, function, keyWho may use this resource, including other accounts
Trust policyRoleWho may assume the role
Permissions boundaryUser or roleMaximum permissions the identity can have
Session policyPassed to AssumeRoleNarrows one session below the role

A resource policy has a Principal element. An identity policy does not, because the principal is the identity it is attached to.

Fine grained access control

Use conditions to narrow a policy to least privilege.

  • Resource ARNs: limit a statement to one bucket prefix, such as arn:aws:s3:::reports/${aws:username}/*.
  • Condition keys: aws:SourceIp, aws:SecureTransport, aws:RequestedRegion and aws:PrincipalOrgID restrict where and how the call is made.
  • Tags (ABAC): compare aws:PrincipalTag/team with aws:ResourceTag/team so one policy serves many teams.
  • DynamoDB: the dynamodb:LeadingKeys condition limits a user to items whose partition key matches their identity.
  • Confused deputy protection: a resource policy for a service principal should include aws:SourceArn or aws:SourceAccount.

Security tokens and MFA

Temporary credentials include a session token. To require MFA, add a condition on aws:MultiFactorAuthPresent set to true. A caller who has MFA gets MFA protected temporary credentials by calling sts:GetSessionToken with the device serial number and the current code.

{
  "Effect": "Deny",
  "Action": "s3:DeleteObject",
  "Resource": "arn:aws:s3:::reports/*",
  "Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}}
}

Presigned URLs

A presigned URL gives a caller time limited access to one object without AWS credentials. Your code signs the URL, and anyone holding it can do the one action it was signed for until it expires.

For S3, call the SDK, for example generate_presigned_url with get_object or put_object, and set ExpiresIn in seconds. The URL carries the permissions of the credentials that signed it.

  • With an IAM user's long term keys, the maximum lifetime is seven days.
  • With temporary credentials, such as a Lambda execution role, the URL stops working when those credentials expire, even if you asked for longer.
  • The signer needs permission for the action. A URL signed by a principal that lacks s3:GetObject returns AccessDenied.

For CloudFront, use signed URLs for one file and signed cookies for many files. Signing uses a key pair: the public key is added to a CloudFront key group that the distribution trusts, and your application signs with the private key. A canned policy sets an expiry only; a custom policy can also restrict the IP address and a start time. Pair this with origin access control so the S3 bucket accepts requests only from CloudFront.

Clientasks the apprequests a linkAppsigns with its credentialsURL with signature and expiryClientGET or PUT directlyS3checks signature

How the exam asks about this

  • "Users must download a private report for 15 minutes without AWS accounts" -> generate a presigned URL with a 900 second expiry.
  • "Only users who signed in with MFA may delete objects" -> a policy condition on aws:MultiFactorAuthPresent.
  • "A Lambda function in account A reads a bucket in account B" -> a bucket policy in B allows the function's role, and the role's policy in A allows the action.

What to remember for the exam

  • Default deny, explicit deny wins, and cross account access needs an allow on both sides.
  • Resource policies have a Principal. Identity policies do not.
  • Permissions boundaries and SCPs limit permissions and never grant them.
  • Use ABAC with aws:PrincipalTag and aws:ResourceTag to scale one policy across teams.
  • A presigned URL inherits the signer's permissions and dies when the signing credentials expire.
  • CloudFront uses signed URLs or cookies with a trusted key group. S3 presigned URLs do not.
Watch out

Do not give a presigned URL a longer lifetime than the credentials that signed it. A one day link signed by a one hour role session stops after the hour.

Common mistakes

Granting broad actions to fix an AccessDenied. Read the error, find which policy is missing the allow, and add only that action on that resource.

Forgetting the second side of a cross account grant. An allow in the bucket policy alone is not enough when the caller's identity policy does not allow the action.

Using a presigned URL for sensitive data with a long expiry. Anyone who has the link can use it. Keep the expiry as short as the task needs.

Check yourself

  • When does a presigned URL generated by a Lambda function stop working?

    When it expires or when the function's temporary role credentials expire, whichever comes first.

  • How do you let one policy give each team access only to resources tagged with its team name?

    Attribute based access control: compare aws:PrincipalTag/team with aws:ResourceTag/team in a condition.

  • What is needed for a role in account A to read an S3 object in account B?

    An allow in the bucket policy in B for that role, and an allow in the role's own identity policy in A.

Topic 2 of 6 in Security

Test yourself on Security

The full AWS DVA-C03 question bank has 850 questions, with timed practice exams and an explanation for every answer.

This study guide is independent and is not affiliated with, endorsed by, or sponsored by AWS. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.