KSI-IAM-JITAuthorizing Just-in-Time
A least-privileged, role and attribute-based, and just-in-time security authorization model is used and persistently reviewed for all user and non-user accounts and services.
Mapped NIST 800-53 controls (38)
- recipe17
- KSI only21
The mark says whether an authored AWS recipe fetches evidence for the control; the tier strip shows which Rev5 baselines also require it — where automated KSI evidence doubles as Rev5 control evidence. = in the class B, C and D baselines, left to right
- recipe— an authored recipe collects evidence for this control
- KSI only— a Key Security Indicator reaches it, but no recipe is authored yet
- orphan— no Key Security Indicator reaches it — a person writes it up instead
- recipe · 1 recipeAC-02ACIn baseline B, C, D
- KSI onlyAC-02 (01)ACIn baseline C, D
- recipe · 1 recipeAC-02 (02)ACIn baseline C, D
- recipe · 1 recipeAC-02 (03)ACIn baseline C, D
- recipe · 1 recipeAC-02 (04)ACIn baseline C, D
- KSI onlyAC-02 (06)ACIn no class baseline
- recipe · 2 recipesAC-03ACIn baseline B, C, D
- KSI onlyAC-04ACIn baseline C, D
- KSI onlyAC-05ACIn baseline C, D
- recipe · 2 recipesAC-06ACIn baseline C, D
- recipe · 1 recipeAC-06 (01)ACIn baseline C, D
- KSI onlyAC-06 (02)ACIn baseline C, D
- recipe · 1 recipeAC-06 (05)ACIn baseline C, D
- recipe · 1 recipeAC-06 (07)ACIn baseline C, D
- KSI onlyAC-06 (09)ACIn baseline C, D
- KSI onlyAC-06 (10)ACIn baseline C, D
- recipe · 1 recipeAC-07ACIn baseline B, C, D
- recipe · 1 recipeAC-17ACIn baseline B, C, D
- KSI onlyAC-20 (01)ACIn baseline C, D
- KSI onlyAU-09 (04)AUIn baseline C, D
- recipe · 1 recipeCM-05CMIn baseline B, C, D
- recipe · 1 recipeCM-07CMIn baseline B, C, D
- KSI onlyCM-07 (02)CMIn baseline C, D
- KSI onlyCM-07 (05)CMIn baseline C, D
- KSI onlyCM-09CMIn baseline C, D
- recipe · 1 recipeIA-04IAIn baseline B, C, D
- KSI onlyIA-04 (04)IAIn baseline C, D
- KSI onlyIA-07IAIn baseline B, C, D
- KSI onlyPS-02PSIn baseline B, C, D
- KSI onlyPS-03PSIn baseline B, C, D
- recipe · 1 recipePS-04PSIn baseline B, C, D
- recipe · 1 recipePS-05PSIn baseline B, C, D
- KSI onlyPS-06PSIn baseline B, C, D
- KSI onlyPS-09PSIn baseline B, C, D
- KSI onlyRA-05 (05)RAIn baseline C, D
- KSI onlySC-02SCIn baseline C, D
- recipe · 1 recipeSC-23SCIn baseline C, D
- KSI onlySC-39SCIn baseline B, C, D
Collect evidence (4)
Authored AWS recipes whose output is evidence for KSI-IAM-JIT. This mapping is this project’s opinion (overlay v3.0.0), versioned separately from the dataset — the upstream FedRAMP rules name none of these tools.
- partialActive unused-access findings identifying IAM roles, access keys, console passwords, and service/action-level permissions that have not been used within the configured age, driving right-sizing and removalcontinuouscliiam-access-analyzer-unused-accessIAM Access Analyzer
Use list-findings-v2 (list-findings is external-access only and does not return unused-access findings). Requires an existing ACCOUNT_UNUSED_ACCESS analyzer; create one with create-analyzer --type ACCOUNT_UNUSED_ACCESS --configuration '{"unusedAccess":{"unusedAccessAge":90}}'. Target zero ACTIVE unused-permission findings for privileged roles. An empty findings list is meaningful only if an analyzer exists, is ACTIVE, and its unusedAccessAge equals the review period the SSP declares; entities younger than the tracking period, and principals or accounts excluded by tag, never appear as findings. UnusedPermission findings are computed for roles, so IAM users' unused permissions are outside this output, and AC-06 (07)(a)'s periodic review is a human record — which is why this is partial.
- narrativeDocumented just-in-time / break-glass privilege-elevation process backed by IAM Identity Center permission sets and account assignments, showing privileged access is role/attribute-based, time-bound, and approval-gated rather than standingquarterlycliidentity-center-jit-elevation-workflowIAM Identity Center
The API proves RBAC structure and bounded session duration, but it cannot by itself prove that each elevation was requested, approved, and time-limited just-in-time. The approval/break-glass workflow and its evidence (tickets, approvals, deprovisioning records) are a documented process; attach the runbook and sampled approval records. Do not present the permission-set listing alone as proof of JIT.
- partialThe enforced half of who may change what: the service control policy type actually enabled in the organization root, the customer-authored SCPs and the roots, OUs and accounts each one is attached to, and the permissions boundary carried by every principal your own tagging marks as a change authoritycontinuousclichange-authority-restrictions-and-enforcementAWS Organizations · AWS IAM
CM-5 asks for physical AND logical access restrictions associated with changes that are defined, documented, approved and enforced. This recipe reaches one adjective and one verb. The adjective it does not reach is PHYSICAL. No AWS API returns anything about physical access to the hardware a change is made on; under the shared responsibility model that half belongs to the IaaS provider and is inherited — read it from the provider's own authorization package and the FedRAMP customer responsibility matrix, not from this output. A collection that presents these six calls as CM-5 evidence without saying so has answered half a control and labelled it whole. The verb it does reach is ENFORCE, and it reaches it properly: an SCP is not a description of a restriction, it is the restriction, evaluated by AWS on every request from every member account, and list-targets-for-policy is the difference between a policy that exists and a policy that applies to something. Two gaps keep this partial, not one. The first is approval — that the enforced set IS the documented and approved set is a comparison against a change-management record, and no call returns it. The second is subject matter, and it is the easier one to miss: the assertions below show THAT a customer-authored SCP is enforced, never WHAT it restricts. An SCP denying mechanicalturk:* satisfies every clause here exactly as well as one denying ec2:ModifyInstanceAttribute. The fourth call exists to close that by putting the policy document in the evidence — Content is returned as a JSON string and must be parsed — but no assertion can grade a policy document, so the phrase that makes this CM-5 rather than AC-3, 'associated with changes', stays a human read. Both gaps are reconciliations against your own records; the reconciliation is the CM-5 artifact and this output is the column it is reconciled against. Four ways this evidence is vacuous if it is read naively. Three are behaviour AWS documents in as many words; the fourth is an inference from a field being a list, flagged as such rather than dressed up as a citation. A policy type that has never been enabled is ABSENT from Roots[].PolicyTypes rather than present with a Status of DISABLED — the enum has no such value — so a clause of the form 'every SCP policy type entry is ENABLED' is true over an organization where SCPs were never turned on at all, which is why one assertion tests that the entry exists before another reads it. AWS attaches the managed FullAWSAccess policy to EVERY root, OU and account when it is created, so both a non-empty Policies[] and a non-empty Targets[] are the default state of a working organization rather than a restriction anyone wrote — which is why one assertion counts only the AwsManaged false subset, and why calls four and five are bound to a customer-authored policy id instead of any policy id. FeatureSet CONSOLIDATED_BILLING makes SCPs unavailable outright, so on such an organization every policy in the list is inert. And an SCP attached to nothing returns an empty Targets[]: that one AWS does not state, it follows from Targets being a list, and the assertion that rests on it should be read as an inference. The scope edge that matters most to an assessor is that SCPs do not restrict the management account. AWS states this three times on its own page and lists it first among the tasks SCPs cannot restrict: SCPs affect only member accounts, including member accounts designated as delegated administrators, and they have no effect on users or roles in the management account. The account with the broadest reach over the organization is the one account this evidence says nothing about, and its change restrictions have to come from identity-based policy and permission boundaries inside it — which is what the sixth call collects, and why the sixth call has to be run there. SCPs also do not affect service-linked roles at all, and they do not affect principals from accounts outside the organization even when a resource-based policy in your account grants those principals access. Read an SCP for what it is: a ceiling, never a grant. AWS is explicit that no permissions are granted by an SCP and that effective permissions are the intersection of what the SCP allows with what identity-based and resource-based policies allow — a principal with no IAM permissions has no access under the most permissive SCP in the world. Where a permissions boundary is also present, AWS documents that the boundary, the SCP and the identity-based policy must ALL allow the action, which is why the sixth call is collected beside the first five rather than instead of them. One failure mode worth writing into the assessment because it is silent and total: disabling the SCP policy type in a root automatically detaches every SCP from every OU, account and organization in that root, and re-enabling it does not restore the attachments — the root reverts to FullAWSAccess alone and the previous attachments are lost and not automatically recoverable. After such an event list-policies still returns every authored policy, unchanged, while nothing is enforced anywhere. The Roots[].PolicyTypes reading and the Targets[] reading are what separate those two worlds, and a collection that skips them cannot tell them apart. The permissions-boundary assertion is scoped by your own tagging rather than written as a claim over the account, for the same reason as in the AC-02 (02) recipe: no AWS call knows which of your roles are supposed to be the change authorities. It passes without saying anything on an estate that tags none, so treat the tagging standard as a written control with a manual sample rather than as coverage. What actually happened, as opposed to what was permitted, is a different recipe: CloudTrail's non-read-only event history, collected under CM-03 alongside the Config resource timeline and the Systems Manager change-request records. This one is about the restriction; that one is about the change.
- partialEvery identifier the account has issued, with the date it was assigned and the AWS-generated unique id behind it; the workforce identifiers issued through IAM Identity Center and the external issuer each one came from; and the CloudTrail record of identifiers being deleted, which is the only dated evidence of a name becoming free to reusecontinuouscliidentifier-assignment-and-reuse-preventionAWS IAM · AWS IAM Identity Center · AWS CloudTrail
IA-04 is four verbs — receive authorization for an identifier, select it, assign it to the intended party, and prevent its reuse for a defined period. AWS proves the third completely, gives real but bounded evidence for the fourth, and returns nothing at all for the first two. Assignment is the easy half and it is genuinely complete: every identifier in the account is enumerable with the date it was assigned and the AWS-generated unique id behind it. Selection and authorization are records about a decision, not about a resource, and no call returns them. Reuse is where this control is usually mis-evidenced, and AWS's own documentation is unusually direct about why. Within an account a friendly name for a user, group, role or policy must be unique — but only while it exists. AWS documents the exact failure IA-04's reuse clause exists to prevent: an employee named John leaves, the IAM user John is deleted, a new employee named John arrives, a new IAM user John is created, and a policy written against the friendly name grants the new John access to what the old John left behind. Nothing in AWS prevents that. There is no cooling-off period, no reserved-name list, no setting. What AWS guarantees instead is narrower and worth reading precisely: the unique id is never reused, so the old John's AIDA... and the new John's AIDA... differ, and a resource-based policy or an aws:userId condition written against the unique id cannot be inherited by a successor. The identifier that is protected from reuse is the one nobody uses in policy by default. So the honest evidence for the reuse limb is a comparison, not a field: DeleteUser events dated against the CreateDate of a live identifier bearing the same name — UserDetailList[].CreateDate is collected here and is the right side of that comparison, which is why no CreateUser lookup is listed. Note what to read on the left side: Username on a lookup-events entry is the REQUESTER, the administrator who ran the deletion, so the deleted identifier has to come out of the CloudTrailEvent JSON at requestParameters.userName. Reading Username as the deleted name is the easy mistake and it produces a comparison against the wrong string entirely. Three limits on the comparison, all hard. lookup-events reads management events for the last 90 DAYS only, so any reuse period your SSP states beyond 90 days cannot be evidenced from this call at all — a CloudTrail Lake event data store or an S3 trail with a longer retention is what closes that, and it is a different collection. The call is also Region-bound in a way that has nothing to do with GovCloud: IAM is a global service, its events are recorded in one Region, and lookup-events shows them in the Region where they occurred — so the same command run anywhere else returns an empty Events[] while succeeding, which is indistinguishable from a window in which nobody was deleted. And the comparison itself is a join between two commands' outputs, which the assertion grammar cannot express: it compares a field to a constant, never one response to another. Both of those are why the reuse limb is written into the notes as a manual reconciliation rather than dressed up as a clause below. The IAM users this recipe enumerates are also, on a well-run estate, the smallest part of the answer. Workforce identifiers should be issued in an external identity provider and reach AWS through IAM Identity Center, where the identifier's authority is the ExternalIds pair naming the issuer — which is what the third call reads. An account with an empty UserDetailList and a populated identity store is in better shape than the reverse, and an assertion that ranges over IAM users will say almost nothing about it. Read the two together or read neither. The identity-store calls are collected as EVIDENCE and deliberately carry no assertion. An earlier draft asserted that an Identity Center instance exists and that every identity-store user carries ExternalIds; both were withdrawn, because they fail an account that federates through an IAM SAML provider instead — which is a different architecture, not an IA-04 defect — and because the second is vacuous anyway on an instance with zero users, so the first does not guard it. An assertion that encodes an architectural preference as a control failure is worse than a paragraph saying which architecture this evidence reads best. Emptiness traps to state rather than assert. list-instances returns a list whose documented minimum length is zero and whose maximum is ten, so an account with no instance returns an empty Instances[] rather than an error, and reading only the first entry misses up to nine. A DeleteUser lookup over a window in which nobody was deleted returns an empty Events[], indistinguishable from a window in which the trail was not recording. And GroupDetail carries no Tags, so the authorization-tag clause below cannot be extended to group identifiers at all; device and service identifiers are outside every call here. Roles and groups are collected alongside users because their names are identifiers the control covers, and because the same reuse behaviour applies: RoleId and GroupId are never reused, while RoleName and GroupName are free the moment the resource is deleted.
Default evidence owed by every indicator (5)
From info.default_artifacts.KSI — no indicator carries its own artifacts; requirement-specific evidence lives on /evidence.
- Explanation of measures (and their objectives) that demonstrate the Key Security Indicator, or an explanation of the reason and resulting risk to customers for not having measures available for that Key Security Indicator.
- Explanation of the cycle for any measures that are implemented persistently (if applicable).
- Verification that the measures demonstrate the Key Security Indicator, or that the reason for not having them is accepted.
- Verification that the automation in place is accurate and sufficient to demonstrate appropriate measures for the Key Security Indicator, or that automation is not necessary for each measure.
- Validation that the measures are accurately produced and are in place and working as intended, or that the reason for not having them is valid.
Defined terms used (1)
- Persistently
- Occurring in a firm, steady way that is repeated over a long period of time in spite of obstacles or difficulties. Persistent activities may vary between actors, may occur irregularly, and may include interruptions or waiting periods between cycles. These attributes of persistent activities should be intentional, understood, and documented; the status of persistent activities will always be known.
The Identity and Access Management run (6)
6/6 have an authored AWS recipe- 3 authored recipesKSI-IAM-AAMAutomating Account Management
- 5 authored recipesKSI-IAM-APMAdopting Passwordless Methods
- 11 authored recipesKSI-IAM-ELPEnsuring Least Privilege
- 4 authored recipesKSI-IAM-JITAuthorizing Just-in-Timeyou are here
- 2 authored recipesKSI-IAM-SNUSecuring Non-User Authentication
- 1 authored recipeKSI-IAM-SUSResponding to Suspicious Activity