@@ -288,6 +288,18 @@ def _current_cluster_server(self):
288288 out , _ = _run_command (cmd )
289289 return (out or "" ).strip ().strip ("'" )
290290
291+ def _auth_can_i (self , namespace , sa , verb , resource ):
292+ """Run auth can-i for an impersonated ServiceAccount and return normalized output."""
293+ out , err = _run_command (
294+ "kubectl auth can-i " + verb + " " + resource
295+ + " -n " + namespace
296+ + " --as=system:serviceaccount:" + namespace + ":" + sa
297+ + self .kubeconfig_flag
298+ )
299+ if err and ("unable to connect to the server" in err .lower () or "i/o timeout" in err .lower ()):
300+ self .skipTest ("Skipping authz assertion due to transient API connectivity issue: " + err .strip ())
301+ return (out or "" ).strip ().lower ()
302+
291303 def test_provider_kubeconfig_all_fields_nonempty (self ):
292304 """Provider kubeconfig: every field that should exist is non-empty."""
293305 ns = "kubeplus-test-prov-" + uuid .uuid4 ().hex [:8 ]
@@ -436,6 +448,74 @@ def test_consumer_can_create_deployment_but_not_pod(self):
436448 _run_command ("kubectl delete deployment --all -n " + ns + self .kubeconfig_flag + " 2>/dev/null" )
437449 self ._delete_for_cleanup (ns , sa = consumer_sa )
438450
451+ def test_update_revoke_json_yaml_have_same_auth_can_i_effect (self ):
452+ """
453+ update/revoke with equivalent JSON and YAML permission files should yield same auth outcome:
454+ baseline deny -> allow after update -> deny after revoke.
455+ """
456+ ns = "kubeplus-test-uprev-" + uuid .uuid4 ().hex [:8 ]
457+ sa = "uprev-sa"
458+ json_file = os .path .join ("tests" , "permission_files" , "permissions-example1.json" )
459+ yaml_file = os .path .join ("tests" , "permission_files" , "permissions-example1.yaml" )
460+ self .assertTrue (os .path .exists (os .path .join (ROOT , json_file )))
461+ self .assertTrue (os .path .exists (os .path .join (ROOT , yaml_file )))
462+ try :
463+ _run_command ("kubectl create ns " + ns + self .kubeconfig_flag )
464+ _run_command ("kubectl create sa " + sa + " -n " + ns + self .kubeconfig_flag )
465+
466+ def run_flow (permission_file ):
467+ baseline = self ._auth_can_i (ns , sa , "create" , "secrets" )
468+ self .assertIn (baseline , ["yes" , "no" ])
469+ proc_update = subprocess .run (
470+ [
471+ sys .executable ,
472+ os .path .join (ROOT , SCRIPT ),
473+ "update" ,
474+ ns ,
475+ "-c" ,
476+ sa ,
477+ "-p" ,
478+ permission_file ,
479+ ] + self .kubeconfig_arg ,
480+ cwd = ROOT ,
481+ capture_output = True ,
482+ text = True ,
483+ timeout = 120 ,
484+ )
485+ self .assertEqual (proc_update .returncode , 0 , proc_update .stderr )
486+ after_update = self ._auth_can_i (ns , sa , "create" , "secrets" )
487+ proc_revoke = subprocess .run (
488+ [
489+ sys .executable ,
490+ os .path .join (ROOT , SCRIPT ),
491+ "revoke" ,
492+ ns ,
493+ "-c" ,
494+ sa ,
495+ "-p" ,
496+ permission_file ,
497+ ] + self .kubeconfig_arg ,
498+ cwd = ROOT ,
499+ capture_output = True ,
500+ text = True ,
501+ timeout = 120 ,
502+ )
503+ self .assertEqual (proc_revoke .returncode , 0 , proc_revoke .stderr )
504+ after_revoke = self ._auth_can_i (ns , sa , "create" , "secrets" )
505+ return baseline , after_update , after_revoke
506+
507+ json_result = run_flow (json_file )
508+ yaml_result = run_flow (yaml_file )
509+ self .assertEqual (json_result , yaml_result )
510+ self .assertEqual (json_result [1 ], "yes" )
511+ self .assertEqual (json_result [2 ], "no" )
512+ finally :
513+ _run_command ("kubectl delete clusterrole " + sa + "-update" + self .kubeconfig_flag + " 2>/dev/null" )
514+ _run_command ("kubectl delete clusterrolebinding " + sa + "-update" + self .kubeconfig_flag + " 2>/dev/null" )
515+ _run_command ("kubectl delete configmap " + sa + "-perms -n " + ns + self .kubeconfig_flag + " 2>/dev/null" )
516+ _run_command ("kubectl delete sa " + sa + " -n " + ns + self .kubeconfig_flag + " 2>/dev/null" )
517+ _run_command ("kubectl delete namespace " + ns + " --ignore-not-found --wait=false" + self .kubeconfig_flag )
518+
439519
440520if __name__ == "__main__" :
441521 unittest .main ()
0 commit comments