Verify fresh ESO reconciliation and safely retire unused delivery tokens
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a06ecb-456a-71c2-b41e-0755d336e883
This commit is contained in:
parent
dfc1641c49
commit
153223983f
1 changed files with 34 additions and 1 deletions
|
|
@ -121,18 +121,51 @@ def run(args, receipt):
|
|||
# JSON Patch tests the observed spec atomically; replace only authentication.
|
||||
patch = [{'op':'test','path':'/spec','value':live['spec']}, {'op':'replace','path':'/spec/provider/vault/auth','value':b['auth']}]
|
||||
command(kube + ['patch', 'clustersecretstore', lane['store'], '--type=json', '-p', json.dumps(patch)])
|
||||
before = data(command(kube + ['-n', lane['namespace'], 'get', 'externalsecret', lane['name'], '-o', 'json'])).get('status', {}).get('refreshTime')
|
||||
command(kube + ['annotate', 'clustersecretstore', lane['store'], 'force-sync=' + str(time.time_ns()), '--overwrite'])
|
||||
command(kube + ['-n', lane['namespace'], 'annotate', 'externalsecret', lane['name'], 'force-sync=' + str(time.time_ns()), '--overwrite'])
|
||||
command(kube + ['wait', '--for=condition=Ready', 'clustersecretstore/' + lane['store'], '--timeout=45s'])
|
||||
command(kube + ['-n', lane['namespace'], 'wait', '--for=condition=Ready', 'externalsecret/' + lane['name'], '--timeout=45s'])
|
||||
for attempt in range(20):
|
||||
status = data(command(kube + ['-n', lane['namespace'], 'get', 'externalsecret', lane['name'], '-o', 'json'])).get('status', {})
|
||||
if status.get('refreshTime') != before and any(c['type'] == 'Ready' and c['status'] == 'True' for c in status.get('conditions', [])):
|
||||
row['refresh_time'] = status['refreshTime']
|
||||
break
|
||||
time.sleep(2)
|
||||
else:
|
||||
raise LaneError('fresh_reconcile_not_observed')
|
||||
compare_custody(kube, lane)
|
||||
row.update(status='passed', unchanged_workload_values=True, store_ready=True, external_secret_ready=True)
|
||||
if args.action == 'cleanup':
|
||||
# Retired delivery tokens only; never delete workload Secrets or KV data.
|
||||
stores = data(command(kube + ['get', 'clustersecretstores,secretstores', '-A', '-o', 'json']))['items']
|
||||
for lane, row in zip(lanes, receipt['lanes']):
|
||||
name = lane['store'] + '-eso-token'
|
||||
for store in stores:
|
||||
ref = store['spec'].get('provider', {}).get('vault', {}).get('auth', {}).get('tokenSecretRef', {})
|
||||
require(ref.get('name') != name, 'retired_token_still_referenced')
|
||||
secret = data(command(kube + ['-n', 'external-secrets', 'get', 'secret', name, '-o', 'json']))
|
||||
old_token = base64.b64decode(secret['data']['token']).decode()
|
||||
lookup = bao(['write', '-format=json', 'auth/token/lookup', '-'], payload={'token': old_token}, allow_failure=True)
|
||||
if lookup.returncode == 0:
|
||||
policies = set(data(lookup)['data']['policies'])
|
||||
require(policies <= {lane['policy'].removesuffix('-eso'), 'default'}, 'retired_token_scope_requires_review')
|
||||
revoke(old_token)
|
||||
row['retired_token_revoked'] = True
|
||||
else:
|
||||
require(b'400' in lookup.stderr and (b'bad token' in lookup.stderr.lower() or b'invalid token' in lookup.stderr.lower()), 'retired_token_invalidity_unproven')
|
||||
row['retired_token_already_invalid'] = True
|
||||
check = bao(['token', 'lookup', '-format=json'], token=old_token, allow_failure=True)
|
||||
require(check.returncode != 0 and b'403' in check.stderr, 'retired_token_denial_unproven')
|
||||
options = {'apiVersion':'v1','kind':'DeleteOptions','preconditions':{'uid':secret['metadata']['uid'],'resourceVersion':secret['metadata']['resourceVersion']}}
|
||||
command(kube + ['delete', '--raw', '/api/v1/namespaces/external-secrets/secrets/' + name, '-f', '-'], payload=options)
|
||||
row['retired_token_secret_removed'] = True
|
||||
receipt['status'] = 'passed'
|
||||
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description=__doc__)
|
||||
p.add_argument('action', choices=['apply', 'verify'])
|
||||
p.add_argument('action', choices=['apply', 'verify', 'cleanup'])
|
||||
p.add_argument('--kubeconfig', required=True)
|
||||
p.add_argument('--receipt', required=True)
|
||||
p.add_argument('--confirm', required=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue