fjall unlock recovers a resource that a stranded deny policy has locked everyone out of. It is a break-glass command. It runs an STS AssumeRoot session in the member account that owns the resource, because a quarantine deny blocks every role principal, including the cascade role Fjall normally deploys with.
Prerequisites
Prerequisites
This command does not read
infrastructure.ts and does not take -a, --app. Run it from anywhere.Unlock a quarantined bucket
bucket is the only subcommand. fjall unlock on its own prints the command help and exits 1.
What Happens
- Options are validated. The bucket name must be 3 to 63 characters and
--accountmust be a 12-digit AWS account id. - The CLI requires an authenticated session.
- Without
--acknowledge-root-session, the command refuses. It prints what the root session does, what the delete destroys, and the exact command to re-run. No AWS call is made. - It resolves the organisation root profile from your org config. If no organisation account is connected, the command stops and points you at
fjall connect. - It picks the region:
--regionfirst, then the root profile’s home region, thenus-east-2. AssumeRoot needs a regional STS endpoint, so the region is load-bearing. - It assumes root in the member account, bounded by the AWS managed root-task policy
arn:aws:iam::aws:policy/root-task/S3UnlockBucketPolicyfor a maximum of 900 seconds. - It captures the live policy with
GetBucketPolicy, then removes it withDeleteBucketPolicy. Capture runs first on purpose:DeleteBucketPolicydoes not record the policy body in CloudTrail, so the captured JSON is the only forensic copy. - It prints the captured policy and the loss warning. The policy is the result, so it goes to stdout verbatim, unmasked and byte for byte, because it is the only surviving copy of the document the unlock just deleted. The
Captured bucket policy (now deleted):heading and theWarning:line are conversation on stderr, and the warning is still credential-masked.
After the unlock
CloudFormation does not reconcile an out-of-band policy deletion on the next deploy. Review the captured policy and re-put the statements the bucket needs, starting with the TLS-only deny. The captured policy is on stdout and nowhere else, so redirect it to a file to keep it:fjall compliance fix --issue-id <id> --execute --acknowledge-root-session runs the remediation for that issue behind the same root-session gate.
Bucket with no policy
If the bucket carries no policy at all, it is not policy-locked. The command reports that there is nothing to unlock and deletes nothing.No dry run
There is no--dry-run flag. The refusal in step 3 is the preview: it names the account, the bucket, the region and the consequences before anything is touched.
Agent mode
With--agent, a missing acknowledgement emits an action_required block with the action root_session_acknowledgement_required and a choice carrying the full re-run command. An agent can resolve it on its own, no human input required.
A successful unlock returns these fields:
--fields selects from exactly those names and is validated before the authentication round-trip, so an unknown field fails fast rather than after the call to AWS.
capturedPolicy rides the result block verbatim, unmasked and never thinned by --budget, because it is the artefact the caller ran the command to receive. warning is prose about the artefact, so it masks like everything else.
Options
All flags below belong tofjall unlock bucket. The parent fjall unlock group accepts --non-interactive.
Next Steps
S3 Bucket
Declare bucket policy and encryption settings in
infrastructure.ts.fjall drift
Detect and repair infrastructure changed outside CloudFormation.
fjall connect
Connect the organisation and member AWS accounts the unlock relies on.
Deploy the organisation
Set up the organisation tier that enables centralised root access.