Skip to content

Identity Policy JSON Reference

A policy is a file with a name and a list of statements. The sample below is what deployport iam identity-policy example prints, so you can generate it rather than retype it. A statement allows or denies a list of actions on a list of resources. It is HuJSON, so comments and trailing commas are allowed.

example.json
{
"name": "self-service-keys", // name of the policy
"statements": [
{
"actions": [
"iam:CreateUserSSHKey",
"iam:DeleteUserSSHKey", // actions that manage your own SSH keys
],
"resources": [
// ${username} is the caller's own name, so this statement reaches their keys
// however, doesn't work with roles.
"iam:User(${username}).SSHKey(*)",
],
"effect": "allow", // effect of the statement, can be "allow" or "deny"
},
],
}

The policy’s name inside the account, and the name you attach and detach by. It is not the file name.

A list. An identity with several statements gets the union of what they allow, minus anything a deny statement refuses, because a deny wins.

One action per entry, written as <service>:<Action>, for example iam:CreateUserSSHKey. The list is the service’s own action names, so an action is spelled the way the service that authorizes it spells it.

⚠️ An action that does not exist matches nothing, and it fails silently. A statement naming a retired action refuses what it used to allow, with no error at the identity and a refusal at the call site. That is why Write a policy checks what a policy reaches after any platform change that renames an action.

The DRNs the statement applies to, one per entry, written as <service>:<ResourceType>(<name>). A child resource extends its parent’s name, so iam:User(johan).SSHKey(*) is every key on one user, and * in the parentheses is every name at that level.

${username} is substituted with the caller’s own name, so a statement can scope itself without naming anybody. ⚠️ Variables do not resolve for a role, which has no username to substitute, so a policy for a role names its resources literally.

allow or deny, and every statement carries one. A deny wins: a narrow deny carves a hole out of a broad allow, so allowing everything and denying one name is a policy that reaches everything except that name.

The actions and the resource types are the authorizing service’s, not the policy format’s. A service publishes both when it registers, so a new action reaches you without a policy format change, and an action the service never registered is not available to name.