Your encryption-at-rest rule reads a key ARN unknown until apply: block, defer, or constrain the input?
answer
- find out why it is unknown first
- three postures, none of them free
- blocking buys safety, spends trust
- deferring leaves a live window
- measure the unknown rate before enforcing
basics
~20 sDecide per control, not globally: blocking every unknown is safest but taxes teams with failures they cannot act on, deferring the assertion leaves a window where non-compliant infrastructure exists, and constraining the module input removes the unknown wherever you own the code.
solid answer
~50 sFirst diagnose why the key identifier is unknown, because that decides which options exist. Then choose among three. Fail closed — block any change where the attribute cannot be evaluated — and you never ship an unchecked resource, at the price of failures engineers cannot fix themselves and an exemption queue that erodes the gate's credibility. Defer — let the plan pass, record the resource as unevaluated, and assert the property once the value materialises — and you keep teams moving, at the price of a window during which non-compliant infrastructure genuinely exists, plus a named owner for the follow-up. Constrain the input — require the key identifier to arrive as a validated variable or a fixed module value so it is known at plan — and the ambiguity disappears, but only where you control the module. I would pick per control on blast radius, and measure how often the rule actually meets an unknown in report-only mode before making it blocking.
go deeper
Recognise that a rule which cannot see the value has to make a choice, and that quietly passing the change is the one option that is always wrong.
Be able to name the three responses — block on unknown, assert it after the apply, or make the value known at plan — and give one concrete cost of each.
Show that you diagnose why the value is unknown before choosing, and that you measure how often the rule meets an unknown in report-only mode before making it blocking.
Own the tradeoff across the estate: which controls stay preventive whatever the friction, which are honestly detective, and which team absorbs the cost of each decision.
## The situation A control says: this storage must be encrypted with a customer-managed key. The rule reads the attribute naming that key on the resource in the plan. On some changes the attribute holds a literal identifier and the rule works. On others the plan marks it unknown until apply, and the rule has nothing to evaluate. You are the security lead; the rule is yours; the pipeline it gates belongs to a dozen teams. The one answer that is always wrong is to leave the rule as it is and let the unknown produce no finding. Everything else is a genuine tradeoff. ## Step zero: why is it unknown? Before choosing a posture, find out what is producing the unknown, because it changes what is available to you. A key identifier that is unknown because the key is created by the same change is a different problem from one that is unknown because it comes from a lookup deferred to apply, which is different again from one that is unknown because a module passes it through an indirection nobody needs. The third case has a code fix; the first two may not. Answering this first is what separates a senior response from a policy-shaped opinion. ## Option 1 — fail closed on unknown Every change where the attribute cannot be evaluated is blocked. **What it buys:** no resource ever reaches production without this control having actually seen it. The claim "this control is preventive" stays true, and stays true without footnotes. **What it costs:** the false-positive tax. Engineers are stopped by a failure whose cause is not a mistake they made and often not something they can fix at all. Each one becomes a ticket, a Slack thread, or an exemption. Two failure modes follow, and both are worse than the original risk: the exemption path becomes the default route, so the gate is a formality; or teams learn that this gate fires for reasons unrelated to security and start reading its output as noise, which damages every *other* rule you run. Blocking is the right call when the control is high blast radius and the unknown is rare. It is a bad call when the unknown is the common case, because then you have not built a guardrail, you have built a queue. ## Option 2 — defer the assertion Let the plan pass, but record explicitly that this resource was not evaluated, and assert the property once the value exists. **What it buys:** teams keep shipping, and the control still gets checked — later, against something real rather than a prediction. **What it costs:** honesty about what you now have. There is a window between apply and detection in which non-compliant infrastructure exists and is serving traffic. That is acceptable for some properties and not for others. Deferring also converts a preventive control into a detective one, and a detective control is only worth anything if three things are true: someone is named as its owner, its output reaches a human who can act, and there is an agreed remediation — including whether the answer is "fix it" or "destroy it". Deferring without those is not deferring, it is dropping the control while keeping the paperwork. ## Option 3 — constrain the input so the value is known Change the code rather than the rule: require the key identifier to be supplied as a variable with validation against an approved set, or fix it inside an approved module, so that by the time a plan is produced the value is a literal. **What it buys:** the ambiguity is gone rather than managed. The rule becomes evaluable on every plan, the gate stays preventive, and no exemption path is needed. **What it costs:** reach and flexibility. It only works where you own the module or can require its use, it takes module changes and a migration across callers, and it constrains legitimate patterns — a team that genuinely needs a key created in the same change now cannot have one. Do not oversell it in an interview: if the value is inherently produced during apply, no amount of variable validation makes it known at plan. ## How to actually choose A defensible answer picks per control rather than declaring one global posture: - **Blast radius and reversibility.** A property whose violation is quietly correctable after the fact tolerates deferral. One that exposes data the moment the resource exists does not. - **Frequency of the unknown.** Run the rule in report-only mode first and count how many evaluations hit an unknown. If it is a handful a month, block. If it is most of them, blocking is a decision to break the pipeline, and the honest move is to fix the modules or defer. - **Whether a detective control already exists.** If the property is already checked continuously against real resources, deferring costs a window, not the control. - **Who absorbs the cost.** Blocking pushes it onto the teams shipping; deferring pushes it onto whoever owns the follow-up. Pick deliberately, and say out loud which team you just handed work to. The strongest version of this answer usually combines two: constrain the input where you own the module, block on the residual unknowns, and keep a deferred check as the backstop for the paths you do not control.
- How do you decide which controls are allowed to defer?Blast radius and reversibility. A property whose violation can be corrected quietly afterwards tolerates a window; one that exposes data the moment the resource exists does not. I also require that a deferred control has a named owner, an alert that reaches a human, and an agreed remediation. Without those, deferring is just dropping the control with better paperwork.
- A team says this rule blocks them on every single run. What do you do first?Look at the failures, not the team. If most of them are unknowns rather than genuinely bad values, the rule is producing noise about something the team cannot fix, and the defect is mine. Then choose: fix the module so the value is known, or defer this control for that path. Adding them to a permanent exemption list is the answer that guarantees the problem returns.
- Is constraining the input always available?Only where you own the module or can mandate one, and only when the value is not inherently produced during apply. If the identifier genuinely comes into existence during the apply, no variable validation makes it known at plan time, and the honest remaining choices are block or defer. Claiming otherwise in an interview is an easy way to be caught out.
saying these in an interview costs you the question
- Leaves the rule silently passing and calls that a pass
- Blocks every unknown without measuring how often it fires
- Defers the check with nobody owning the follow-up
- Still calls the control preventive after deferring it
- Sends every unknown to a permanent exemption list