Reference

IAM permissions and conditions

Reference for the ABAC permission model: rule shape, actions, resource patterns, identity templates, condition operators and keys, LIST scoping, and group resolution.

Permission shape#

Each IAM user carries one or more permission rules, evaluated per request after SigV4 verification:

{
  "effect": "Allow",
  "actions": ["read", "write", "list"],
  "resources": ["releases/firmware/*"],
  "conditions": {
    "IpAddress": { "aws:SourceIp": "203.0.113.0/24" }
  }
}

effect, actions, and resources are required; conditions is optional.

Effect#

ValueMeaning
AllowGrants access when actions, resources, and conditions all match
DenyBlocks access when it matches — overrides every Allow, whether the Deny comes from the user's direct rules or an inherited group

A request with no matching Allow is implicitly denied.

Actions#

ActionS3 operations
readGetObject, HeadObject
writePutObject, CopyObject, CreateMultipartUpload, UploadPart, CompleteMultipartUpload
deleteDeleteObject, DeleteObjects
listListBuckets, ListObjectsV2, ListMultipartUploads, ListParts
adminCreateBucket, DeleteBucket
*All actions

A user is an admin (admin GUI access, config changes) when at least one Allow rule has actions containing * or admin AND resources containing *.

Resources#

Glob patterns matched against bucket/key:

PatternMatches
*Every bucket and key
releasesBucket-level operations only (list, create)
releases/*Every object in releases
releases/firmware/*Objects under the firmware/ prefix
releases/firmware/fw-2.*Glob on the object key

Bucket-level operations match the bare bucket name (no /*); object operations match bucket/*. Full access to one bucket therefore requires both rules:

[
  { "effect": "Allow", "actions": ["*"], "resources": ["releases"] },
  { "effect": "Allow", "actions": ["*"], "resources": ["releases/*"] }
]

Permission templates#

Resource strings and string condition values accept identity templates:

TemplateExpands to
${iam:username}The authenticated user's name
${iam:access_key_id}The authenticated user's access key ID

Template facts:

  • The iam: prefix is mandatory; a bare ${username} is not substituted. The prefix distinguishes request-time identity substitution from the ${env:NAME} load-time config expansion. A stale bare ${username} leaves a literal, unmatchable resource pattern — so the rule matches nothing and the user is silently denied. The save-time config advisories flag this; see Config advisories.
  • Templates are stored raw in the DB/YAML and expanded when the in-memory IAM index is built, after group permissions are merged into each member user.
  • Identity values are percent-encoded before substitution: a username dana/team* becomes dana%2Fteam%2A, so it cannot inject path separators or wildcards.
  • Unknown templates are rejected by user/group API validation and by declarative IAM apply.

Example — a per-user home prefix in db-archive, shared via the Engineering group:

{
  "effect": "Allow",
  "actions": ["read", "write", "list"],
  "resources": ["db-archive/home/${iam:username}/*"]
}

For dana this expands to db-archive/home/dana/*.

Conditions#

Conditions within a single rule are ANDed — all must match for the rule to apply. Multiple values for the same key are ORed.

Condition operators#

OperatorDescriptionExample
StringEqualsExact string matchs3:prefix = "firmware/"
StringNotEqualsExact string non-matchs3:prefix != "internal/"
StringLikeGlob pattern matchs3:prefix LIKE "home/dana/*"
StringNotLikeGlob pattern non-matchs3:prefix NOT LIKE ".*"
IpAddressCIDR range matchaws:SourceIp in 203.0.113.0/24
NotIpAddressCIDR range non-matchaws:SourceIp NOT in 203.0.113.0/24

Condition keys#

KeyTypeAvailable onValue
aws:SourceIpIP address (CIDR)All requestsClient IP — from the direct connection, or from X-Forwarded-For / X-Real-IP when DGP_TRUST_PROXY_HEADERS=true
s3:prefixStringLIST requestsThe prefix query parameter

With DGP_TRUST_PROXY_HEADERS=true on a proxy exposed directly to the internet, clients can spoof aws:SourceIp via a forged X-Forwarded-For header.

s3:prefix string values accept the identity templates above, with the same storage, expansion, and percent-encoding rules as resource patterns.

JSON format#

{
  "IpAddress": {
    "aws:SourceIp": ["203.0.113.0/24"]
  },
  "StringNotLike": {
    "s3:prefix": "internal/*"
  }
}

ListBucket prefix scoping#

When a user with prefix-scoped permissions (for example { "resources": ["db-archive/home/dana/*"] }) issues a LIST with an empty prefix, or a prefix wider than the policy covers, the proxy admits the request and post-filters the result:

  • Each returned key and CommonPrefix is checked against the user's policy; only keys with read or list permission are returned.
  • Filtered pages carry the response header x-amz-meta-dg-list-filtered: true.
  • is_truncated and the continuation token reflect the engine-level cursor, not the filtered count; the client's max_keys acts as a server-side inspection cap, so a returned page may be smaller than requested.
  • Users whose policy covers the full requested scope receive the engine page unchanged, with no filtering cost.

Workflow-bypass prevention#

A PUT to a non-existent bucket returns 404 NoSuchBucket on every backend — including the filesystem backend, where the underlying FS could create the parent directory. Bucket creation requires the admin action; it cannot occur as a side effect of a write.

Canned policy templates#

The admin GUI (Access → Users → Apply template) offers four starting-point policies. Generated permissions are editable before saving.

TemplatePermissions
Read-onlyread, list on every resource
Developerread, write, list on every resource
AdminAll actions on every resource
Bucket ownerAll actions on one named bucket (selected on apply)

Group resolution#

  • A user's effective permissions are the union of their direct rules and the rules of every group they belong to (for example, dana's direct rules plus the Engineering group's rules).
  • Group permissions are merged into each member at IAM index build time; identity templates expand after this merge.
  • Deny precedence applies across the union: a Deny in any source — direct or inherited — overrides Allows from all sources.
  • OAuth group mapping rules add group memberships on each login; memberships are merged, never replaced, so manual assignments persist.
  • The built-in Administrators group carries { "effect": "Allow", "actions": ["*"], "resources": ["*"] }.