"""Add the admitted public browser client without exposing or replacing other config.""" import argparse,copy,importlib.util,json,secrets,hashlib,base64 from pathlib import Path from datetime import datetime,timezone from urllib.request import build_opener,ProxyHandler,HTTPRedirectHandler from urllib.parse import urlencode,urlparse from urllib.error import HTTPError import yaml spec=importlib.util.spec_from_file_location('rollout','/home/worsch/net-kingdom/sso-mfa/k8s/keycape/approval-clients-rollout.py');r=importlib.util.module_from_spec(spec);spec.loader.exec_module(r) CLIENT='informed-decision-approver';r.IDS=(CLIENT,) KUBE=['kubectl','--kubeconfig','/home/worsch/.kube/config-railiance01'] EXPECTED={'clientId':CLIENT,'displayName':'informed-decision approver surface','audience':'approval-engine','redirectUris':['https://decisions.coulomb.social/auth/callback'],'allowedScopes':['openid','approval:read','approval:approve'],'grantTypes':['authorization_code'],'clientType':'public','tenant':'tenant:platform','mfaRequired':True} class NoRedirect(HTTPRedirectHandler): def redirect_request(self,*args,**kwargs):return None def probe(**overrides): query={'response_type':'code','client_id':CLIENT,'redirect_uri':EXPECTED['redirectUris'][0],'scope':' '.join(EXPECTED['allowedScopes']),'state':secrets.token_urlsafe(32),'nonce':secrets.token_urlsafe(32),'code_challenge':base64.urlsafe_b64encode(hashlib.sha256(secrets.token_bytes(48)).digest()).rstrip(b'=').decode(),'code_challenge_method':'S256'};query.update(overrides) try: response=build_opener(ProxyHandler({}),NoRedirect()).open('https://kc.coulomb.social/authorize?'+urlencode(query),timeout=20) except HTTPError as e:response=e with response: result={'status':response.status} if response.status==302:result['redirect_host']=urlparse(response.headers['Location']).hostname elif response.headers.get('Content-Type','').startswith('application/json'): d=json.load(response);result.update({k:d.get(k) for k in ('error','description','feature')}) return result def main(args,receipt): r.assert_cluster(KUBE) candidates=[c for c in yaml.safe_load(Path('/home/worsch/key-cape/config/service-clients.example.yaml').read_text())['clients'] if c['clientId']==CLIENT] r.require(candidates==[EXPECTED],'public_registration_contract_drift') secret=r.get(KUBE,'secret','keycape-config');deployment=r.get(KUBE,'deployment','keycape') raw,config,_=r.pin.issuer_document(secret) existing=[c for c in config['clients'] if c['clientId']==CLIENT] receipt.update(client_id=CLIENT,existing_registration=bool(existing),before=probe()) if existing: r.require(existing==[EXPECTED],'existing_registration_mismatch');receipt['status']='already_registered';return config_value=r.replacement(secret,[EXPECTED]);candidate=copy.deepcopy(deployment['spec']) image=next(c['image'] for c in candidate['template']['spec']['containers'] if c['name']=='keycape') r.require('@sha256:' in image and candidate['strategy']['type']=='Recreate' and candidate.get('replicas',1)==1,'deployment_pin_required') candidate['template'].setdefault('metadata',{}).setdefault('annotations',{})['key-cape.coulomb.social/informed-decision-registration']=datetime.now(timezone.utc).isoformat() r.patch_object(KUBE,'secret',secret,'/data/config.yaml',config_value,dry=True) r.patch_object(KUBE,'deployment',deployment,'/spec',candidate,dry=True) receipt['status']='preflight_passed' if not args.apply:return r.patch_object(KUBE,'secret',secret,'/data/config.yaml',config_value) receipt['phase']='config_applied' after=r.get(KUBE,'secret','keycape-config');r.require(after['data']==dict(secret['data'],**{'config.yaml':config_value}),'unrelated_config_changed') r.patch_object(KUBE,'deployment',deployment,'/spec',candidate) receipt['deployment']=r.ready(KUBE,image) receipt.update(image_unchanged=image,unrelated_config_preserved=True) checks={'valid_pkce':probe(),'wrong_redirect':probe(redirect_uri='https://example.invalid/callback'),'consume_scope':probe(scope='openid approval:consume'),'missing_pkce':probe(code_challenge='',code_challenge_method='')} receipt['checks']=checks r.require(checks['valid_pkce']['status']==302,'authorization_did_not_reach_login') r.require(all(checks[k]['status'] in (400,403) for k in ('wrong_redirect','consume_scope','missing_pkce')),'authorization_negative_failed') receipt['status']='applied_verified' if __name__=='__main__': p=argparse.ArgumentParser();p.add_argument('--apply',action='store_true');p.add_argument('--receipt',type=Path,required=True);args=p.parse_args() receipt={'observed_at':datetime.now(timezone.utc).isoformat(),'status':'failed','scope':'public browser registration only; no tokens or approval entries issued by this tool'} try:main(args,receipt) except Exception:print('Registration operation failed; inspect the metadata-only receipt.');raise SystemExit(1) from None finally:args.receipt.write_text(json.dumps(receipt,indent=2)+'\n');print(json.dumps(receipt))