Enrolling an unattended machine
Give a server with nobody at the keyboard a device key backed by AWS KMS, enrolled from an operator's machine.
An unattended machine — a server or container running an agent, with no keychain, no
hardware module and nobody at the keyboard — cannot go through the interactive
enrolment ceremony. For that case, Custodian has a device
whose key is an AWS Key Management Service (KMS) key that the machine's IAM task role
may use: unwrapping the master key is an AWS Decrypt call the machine can make
because it carries the role, not a stored secret.
You enrol this device from an operator's own machine, not from the unattended one.
Understand the trade-off first
This device is weaker than a hardware-backed one, and the command says so before it binds anything. The guarantee it carries:
AWS KMS under a task role — the device key is an AWS KMS key the container's task role may use; unwrapping happens inside KMS and the key itself never enters this tool's memory. The downgrade, stated plainly: AWS can unwrap this copy, so this device is protected by a cloud provider's access control rather than by hardware anyone holds — materially weaker than a hardware module, and the price of running unattended — not yet exercised on real hardware — validate on a machine with this store before relying on it
Two consequences to weigh:
- AWS can unwrap this copy. This device is protected by a cloud provider's access control rather than by hardware anyone holds, which is materially weaker than a hardware module and is the price of running unattended.
- Every machine that runs under that task role is the same device. Running several at once does not create several devices, so the device alone does not tell them apart in the audit trail.
Enrol it
You need, in AWS: a KMS key whose policy admits a decrypt capability to nobody but the one IAM task role the unattended machine will run as. Run the command with your own AWS credentials configured (the person enrolling, not the task role):
custodian device enrol \
--label "batch-runner" \
--provider kms_task_role \
--kms-key arn:aws:kms:eu-west-1:111122223333:key/1234abcd-… \
--task-role arn:aws:iam::111122223333:role/custodian-runner--kms-key <arn>— the KMS key this device unwraps with (required).--task-role <arn>— the one IAM role that alone may decrypt (required). Custodian will not guess it; it must be named.
The command prints the consequences, states that approving the device will need AWS
kms:Encrypt access to the key, then checks the key's policy before anything is
wrapped. If the policy — or a grant on the key — admits a decrypt capability to anyone
but the named task role, it refuses rather than warns. For example:
error: refused: the key policy for arn:aws:kms:eu-west-1:111122223333:key/1234abcd-… statement "AllowDecrypt" grants a decrypt capability to any principal ("*"). Wrapping the master key here would let anyone with the ciphertext decrypt it.Anything the check cannot parse or evaluate — an unreadable policy, a condition it cannot judge — is also refused, not trusted. If the check cannot read the policy at all, the message names your own AWS credentials as the thing to check, since the read runs with them:
error: refused: could not read the key policy for arn:aws:kms:… This read uses your own AWS credentials — the operator's, the ones this command is running with — not the task role's. Check that those credentials are configured for the right account and region and permit kms:GetKeyPolicy and kms:ListGrants on the key…When the policy checks out, the command confirms it and prints an approval request:
Key policy verified: arn:aws:kms:eu-west-1:111122223333:key/1234abcd-… admits a decrypt capability to nobody but arn:aws:iam::111122223333:role/custodian-runner.
…
Approval request — copy this whole line to an already-enrolled machine and run
`custodian device approve <request>` there:
eyJsYWJlbCI6…Approve it
Carry the approval request to an already-enrolled operator machine and run
custodian device approve
there. Approving wraps the master key under the KMS key with an Encrypt call, run
with the approving operator's own AWS credentials — so that operator needs
kms:Encrypt on the key. Grant it before you approve, or the approval fails at the
wrap step. --resume does not apply to this device: it holds no local key to resume.
Running the unattended machine
On the unattended machine, name the KMS key with the CUSTODIAN_KMS_KEY environment
variable. Commands that need to unwrap an encrypted value — such as
custodian resolve and
custodian exec — then unwrap through KMS with a single
Decrypt call. If the machine is not running as the task role, the Decrypt is
denied and the command says exactly what is missing:
error: refused: this container cannot decrypt its wrapped master key — the AWS Decrypt call was denied. The task role is missing the kms:Decrypt permission on key arn:aws:kms:… A container without the task role cannot unwrap; run it with the role the key policy admits.