Repository navigation
Description
What to do
Rotate a RabbitMQ dynamic credential under a consumer that holds an open connection, and record what the consumer sees. Decide what each settled decision does about the claim under it that failed keeps rabbitmq in the grant union as a dynamic credential on the condition that this works.
The estate dropped the dynamic credential once, after Vault revoked a RabbitMQ user under a running pod. The cause recorded in fleet-infra is the Vault Agent injector, which rendered once and never renewed the lease. Vault Secrets Operator (VSO) renews a lease and then replaces the credential and restarts its consumers, which the estate already runs for Postgres. No workload has run that cycle against RabbitMQ, and what a client with an open connection sees when its user is deleted is unverified (docs/research/unsupported-claims.md, claims C7 to C9).
The drill writes to the live Vault and the live cluster, so it is run with the maintainer present, in a throwaway namespace, against a throwaway RabbitMQ role and vhost.
- Read the
rabbitmqmount's lease settings from Vault (rabbitmq/config/lease). The bootstrap script passesdefault_ttlandmax_ttlto the role, where the API defines neither, and writes noconfig/lease. - Set a short lease on a drill role, or on the mount for the length of the drill, so that a renewal and a replacement both happen within minutes.
- Deliver the credential with a
VaultDynamicSecretthat names a Deployment inrolloutRestartTargets. The Deployment runs a consumer that holds one AMQP connection open and logs every connection event. - Watch one renewal and one replacement. Record whether the consumer was restarted with the new credential before the old user was deleted, and what the old connection saw.
- Remove the namespace, the role and any changed lease setting.
Done when
- The mount's real lease lifetime is recorded.
- One renewal and one replacement are observed, with the consumer's log of each.
- The result is posted here: either the cycle is clean, or the failure is described well enough to decide between a dynamic and a static credential.
- Nothing the drill created is left in Vault, RabbitMQ or the cluster.
Notes
This runs before chapter 17 (Secrets and access) is rewritten, because a failure reopens the grant decision. It sits outside the map Map: re-establish deploy-kit's goals, rewrite its spec, and order the work until the estate is handed over, which is not held up by it.
Activity
ExtraToast commentedon Oct 29, 2026
Drill result: a RabbitMQ dynamic credential rotated under a connected consumer
Run
369-20261029T114030Zofdrills/rabbitmq-rotation.sh(estate d595317), against kubectl contextpersonal, 2026-10-29 11:40–11:47 UTC.The live mount's lease
Read before the drill and unchanged after it:
sys/mounts/rabbitmq/tuneis{"default_lease_ttl":2764800,"max_lease_ttl":2764800}, andrabbitmq/config/leaseisnone written (No value found at rabbitmq/config/lease). Roleapp-consumer:{"tags":"","vhost_topics":null,"vhosts":{"/":{"configure":".*","read":".*","write":".*"}}}.The drill
A separate engine,
rabbitmq-drill, on the same broker, leasing for 60s up to 240s, so the live mount and its consumer were never touched. VSO (hashicorp/vault-secrets-operator:1.5.1) delivered it with aVaultDynamicSecret(renewalPercent: 67,rolloutRestartTargetsnaming the consumer) to one pika consumer holding one connection, with a 10 s heartbeat and a publish every 5 s.consumer-5b9bcccbdc-rlcx7runs on frankfurt-contabo-1consumer-5b9bcccbdc-rlcx7is terminatingconsumer-66f9fbcf48-h9l25runs on frankfurt-contabo-1consumer-67c6874dbf-lhk7truns on frankfurt-contabo-1consumer-67c6874dbf-lhk7tis terminatingconsumer-5b9bcccbdc-rlcx7start, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-5b9bcccbdc-rlcx7connected, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-5b9bcccbdc-rlcx7sigterm, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-5b9bcccbdc-rlcx7closed (by=consumer), askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-5b9bcccbdc-rlcx7exit, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-66f9fbcf48-h9l25start, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-66f9fbcf48-h9l25connected, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-67c6874dbf-lhk7tstart, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-67c6874dbf-lhk7tconnected, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0rabbitmq-drill/creds/drill/iAEM5ZLyilMkHCm8MSRpuGSM, 60s, userkubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0rabbitmq-drill/creds/drill/iAEM5ZLyilMkHCm8MSRpuGSMrabbitmq-drill/creds/drill/iAEM5ZLyilMkHCm8MSRpuGSMrabbitmq-drill/creds/drill/iAEM5ZLyilMkHCm8MSRpuGSMrabbitmq-drill/creds/drill/iAEM5ZLyilMkHCm8MSRpuGSMkubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0→kubernetes-drill-369-consumer-698afbd0-b82f-44e1-2cda-db8033f5fd20, a 60s leaseconsumer-5f7549c94d-fz8s4runs on frankfurt-contabo-1consumer-66f9fbcf48-h9l25closed (by=broker code=320 text=CONNECTION_FORCED - user 'kubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0' is deleted), askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-66f9fbcf48-h9l25is terminatingconsumer-5f7549c94d-fz8s4start, askubernetes-drill-369-consumer-698afbd0-b82f-44e1-2cda-db8033f5fd20consumer-5f7549c94d-fz8s4connected, askubernetes-drill-369-consumer-698afbd0-b82f-44e1-2cda-db8033f5fd20consumer-66f9fbcf48-h9l25sigterm, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0consumer-66f9fbcf48-h9l25exit, askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0kubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0What the old connection (
kubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0) saw:consumer-66f9fbcf48-h9l25startconsumer-66f9fbcf48-h9l25connectedconsumer-66f9fbcf48-h9l25closed by=broker code=320 text=CONNECTION_FORCED - user 'kubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0' is deletedconsumer-66f9fbcf48-h9l25sigtermconsumer-66f9fbcf48-h9l25exitconsumer-5b9bcccbdc-rlcx7startconsumer-5b9bcccbdc-rlcx7connectedconsumer-5b9bcccbdc-rlcx7sigtermconsumer-5b9bcccbdc-rlcx7closed by=consumerconsumer-5b9bcccbdc-rlcx7exitconsumer-67c6874dbf-lhk7tstartconsumer-67c6874dbf-lhk7tconnectedFailures the consumer logged:
consumer-66f9fbcf48-h9l25askubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0: the broker closed the connection, by=broker code=320 text=CONNECTION_FORCED - user 'kubernetes-drill-369-consumer-32b7a0fd-8be7-17cb-97a3-6ffebc8834e0' is deletedVerdict: the cycle is not clean; the consumer saw 1 failure(s), listed below. That is the evidence for choosing between a dynamic and a static credential.
Done when
ExtraToast commentedon Oct 29, 2026
Drill result: a RabbitMQ dynamic credential rotated under a connected consumer
Run
369-20261029T122236Zofdrills/rabbitmq-rotation.sh(estate 5f1107a), against kubectl contextpersonal, 2026-10-29 12:22–12:28 UTC.The live mount's lease
Read before the drill and unchanged after it:
sys/mounts/rabbitmq/tuneis{"default_lease_ttl":2764800,"max_lease_ttl":2764800}, andrabbitmq/config/leaseisnone written (No value found at rabbitmq/config/lease). Roleapp-consumer:{"tags":"","vhost_topics":null,"vhosts":{"/":{"configure":".*","read":".*","write":".*"}}}.The drill
A separate engine,
rabbitmq-drill, on the same broker, leasing for 60s up to 240s, so the live mount and its consumer were never touched. VSO (hashicorp/vault-secrets-operator:1.5.1) delivered it with aVaultDynamicSecret(renewalPercent: 33,rolloutRestartTargetsnaming the consumer) to one pika consumer holding one connection, with a 10 s heartbeat and a publish every 5 s, which waits 30s after starting before it connects and is Ready only once connected.consumer-68f585c778-5wjc8runs on frankfurt-contabo-1consumer-85969d5ccf-fnb2vruns on frankfurt-contabo-1consumer-85969d5ccf-fnb2vis terminatingconsumer-68f585c778-5wjc8start, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-68f585c778-5wjc8connected, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-85969d5ccf-fnb2vstart, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-85969d5ccf-fnb2vconnected, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-85969d5ccf-fnb2vsigterm, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-85969d5ccf-fnb2vclosed (by=consumer), askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-85969d5ccf-fnb2vexit, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75crabbitmq-drill/creds/drill/UHtSLjjqyadQUQn1p4UQAXwH, 60s, userkubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75crabbitmq-drill/creds/drill/UHtSLjjqyadQUQn1p4UQAXwHrabbitmq-drill/creds/drill/UHtSLjjqyadQUQn1p4UQAXwHrabbitmq-drill/creds/drill/UHtSLjjqyadQUQn1p4UQAXwHrabbitmq-drill/creds/drill/UHtSLjjqyadQUQn1p4UQAXwHkubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75c→kubernetes-drill-369-consumer-fed331bd-5db7-7b84-c77d-9a77838826f4, a 60s leaseconsumer-66f694b8dd-hp7g5runs on frankfurt-contabo-1consumer-66f694b8dd-hp7g5start, askubernetes-drill-369-consumer-fed331bd-5db7-7b84-c77d-9a77838826f4rabbitmq-drill/creds/drill/v77pUVnTw86jhnAI4sPobnUvconsumer-68f585c778-5wjc8is terminatingconsumer-66f694b8dd-hp7g5connected, askubernetes-drill-369-consumer-fed331bd-5db7-7b84-c77d-9a77838826f4consumer-68f585c778-5wjc8sigterm, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-68f585c778-5wjc8closed (by=consumer), askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cconsumer-68f585c778-5wjc8exit, askubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75crabbitmq-drill/creds/drill/v77pUVnTw86jhnAI4sPobnUvkubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75cWhat the old connection (
kubernetes-drill-369-consumer-744c03c5-e53f-2bae-dba0-bf5280cdf75c) saw:12:23:42
consumer-68f585c778-5wjc8start12:24:12
consumer-68f585c778-5wjc8connected12:27:21
consumer-68f585c778-5wjc8sigterm12:27:23
consumer-68f585c778-5wjc8closed by=consumer12:27:23
consumer-68f585c778-5wjc8exitlast successful tick 12:27:18
12:23:42
consumer-85969d5ccf-fnb2vstart12:24:12
consumer-85969d5ccf-fnb2vconnected12:24:14
consumer-85969d5ccf-fnb2vsigterm12:24:17
consumer-85969d5ccf-fnb2vclosed by=consumer12:24:17
consumer-85969d5ccf-fnb2vexitlast successful tick 12:24:12
The replacement came 57 s before RabbitMQ deleted the old user, and the consumer was on the new user 16 s before it (renewal at 33%, a 30 s startup).
Verdict: the cycle is clean: the consumer ran on the new user 16s before RabbitMQ dropped the old one, and no connection was refused or closed by the broker. The dynamic credential holds.
Done when
ExtraToast commentedon Oct 29, 2026
Decision on the result
The maintainer keeps
rabbitmqin the grant union as a dynamic credential, rotated early (2026-10-29).renewalPercent: 67, the replacement raced the old user's deletion: the broker cut the old connection the second the restarted consumer connected. A slower consumer would lose its connection first.renewalPercent: 33, the replacement came 57 s before the deletion, and a consumer that waits 30 s before connecting was on the new user 16 s before it, with nothing refused or force-closed (result).So when chapter 17 (secrets and access) is rewritten and adds the
rabbitmqarm, its renderedVaultDynamicSecretsetsrenewalPercentlow enough for its consumers' restart to finish before the old lease ends;33is the value the drill proved. The findings are indocs/research/unsupported-claims.md, C7 to C9.