Create a permission set
POST/permission-sets
Defines a new permission set for your tenant.
This call touches nothing in AWS. It writes a single row to Prism's database; no IAM role is created and no AWS API is called. A permission set stays inert until you assign it to a principal for an account, and it is that assignment which cuts the role.
Pick name carefully: it is folded into the IAM role name Prism creates
in every account, AWS role names are immutable, and Prism therefore
refuses to rename a permission set for the rest of its life. Names must
be unique within your tenant, but that uniqueness is enforced by a
database constraint rather than by a check in the handler, so a duplicate
name comes back as a 500, not a 409.
An IAM role can hold at most 10 attached policies, and
managed_policies, customer_managed_policy_ids and
policy_reference_ids share that budget. This endpoint does not
reliably enforce it, and going over is not reported to you here. The
total is only counted on a request that also names at least one
customer_managed_policy_ids or policy_reference_ids entry; a request
that busts the budget using managed_policies alone is accepted without
complaint: 11 or 15 ARNs are stored, echoed in the 200, and read back by
a later GET exactly as sent.
Nothing is broken in AWS at that point, because a create touches no AWS at all. The ceiling is AWS's and it bites when the role is finally cut: the first assignment that provisions this permission set into an account is what fails, long after the create said 200.
Read that failure the way POST /permission-set-assignments describes
every provisioning failure, because nothing about this one is special.
The ordinary path deletes the assignment row, so the id that call
handed you starts answering 404 from
GET /permission-set-assignments/{id}; treat that 404 as "the role could
not be cut", not as "this never existed". A row that survives with
status: "FAILED" and a populated errorMessage is the rare case where
Prism could not clean up after itself, worth reading if you get one, but
not what to wait for. Which of the two an over-budget permission set
produces has not been isolated against a live AWS account, so handle
both.
There is no signal at create time either way, so count the three lists yourself before sending.
A failed create can still leave a permission set behind. The row is
written before customer_managed_policy_ids and policy_reference_ids
are checked, so an unknown id returns 500 with the permission set already
created, possibly with the customer-managed policies already attached
and only the references rejected. After a 500, list or fetch before
retrying rather than assuming nothing happened.
Two shape notes. The response is 200, not 201, and carries no
Location header. And its realm is always the empty string, because
the create path builds the response without that field; re-fetch with
GET /permission-sets/{id} if you need the real value.
Request
Responses
- 200
- 400
- 401
- 403
- 404
- 500
The permission set was created. The body carries the stored
definition, with managed_policies, inline_policies and
attributes normalised to [] or {} where you sent nothing; this
operation never returns them as null.
The request body was rejected before anything was written. Either it
was not valid JSON, or one of the three validated fields failed:
session_duration was not one of the five accepted durations,
relay_state was too long or used a forbidden character, or an
inline_policies key broke AWS's policy-name charset.
Note that this is an ordinary error envelope with a single error
string; permission sets do not return the per-field errors array
some other Prism endpoints use.
Authentication failed: the X-API-Token header was missing, malformed,
expired or not recognised.
This response is text/plain, not JSON. It is written by
http.Error in the authentication middleware, which runs before any
handler and therefore before anything that would build a JSON envelope.
A client that unconditionally JSON-parses response bodies will fail on
this one, so check the status code first.
The token is valid, but it is not allowed to act on this tenant.
An API token is minted inside one tenant and stays bound to it for life.
Sending it to a path whose tenant segment names a different tenant is
refused here, in middleware, before the operation runs, so this says
nothing about the resource you asked for, only about which tenant the
path named. Check the tenant server variable against the console the
token was created in.
No tenant matches the tenant segment of the request path.
The permission set could not be created. This status covers several
causes that are arguably client errors and would elsewhere be a 4xx:
a duplicate name within the tenant, an unknown or out-of-tenant id
in customer_managed_policy_ids or policy_reference_ids, and
(only on a request that names at least one entry in one of those two
lists) more than 10 policies across the three attachment fields. An
over-budget request that names neither list is not reported here at
all: it succeeds, as described above. Read error to tell the rest
apart, and remember that the permission set may already exist despite
the failure.