def get_resource_api(api_client: client.ApiClient = None, **kwargs) -> "client.CertificatesV1beta1Api": """ Returns an instance of the kubernetes API client associated with this object. """ if api_client: kwargs["apl_client"] = api_client return client.CertificatesV1beta1Api(**kwargs)
def confirm_certificate_signing_request(context): if context is None: raise SystemExit( "invalid empty context for CertificateSigningRequest given") load_kube(context) api = client.CertificatesV1beta1Api() return general_confirm("CertificateSigningRequest", lambda: api.list_certificate_signing_request(), lambda i: i.metadata.name)
def wait_for_certificate_signing_request_is_away(context, name): if name is None: raise SystemExit( "invalid empty name for CertificateSigningRequest given") if context is None: raise SystemExit("invalid empty name context given") load_kube(context) print("check removal of", "CertificateSigningRequest", name) api = client.CertificatesV1beta1Api() return general_away_check( None, "CertificateSigningRequest", name, lambda: api.read_certificate_signing_request_with_http_info(name))
def remove_certificate_signing_request(context, name): if context is None: raise SystemExit( "invalid empty context for CertificateSigningRequest given") if name is None: raise SystemExit( "invalid empty name for CertificateSigningRequest given") load_kube(context) api = client.CertificatesV1beta1Api() ret, status, _ = api.delete_certificate_signing_request_with_http_info( name) handle_status(ret, status, "CertificateSigningRequest", None, name)
def run_csr_approval(client: k8s.ApiClient, node_csr_spec: Dict[str, Any]) -> None: api = k8s.CertificatesV1beta1Api(client) csrs: k8s.V1beta1CertificateSigningRequestList \ = api.list_certificate_signing_request() now = datetime.utcnow() csrs_to_approve = iterate_csrs(csrs, node_csr_spec) for csr in csrs_to_approve: try: create_approval_patch(csr, now) api.replace_certificate_signing_request_approval( csr.metadata.name, body=csr) except BaseException as e: # Log, but don't quit -> continue processing other CSRs logger.error(e, exc_info=True)
def valiate_approve_csr(csrList, nodeInfoList): # Initialize empty lists ( approvedBootStrappedNodes, approvedNodes, approvedNodesToLabel, approvedCSRs, approvedNodesToTaint, ) = ([], [], [], [], []) # a reference to the API certs_api = client.CertificatesV1beta1Api() # Auth user and groups bootstrapGroups = [ "system:serviceaccounts:openshift-machine-config-operator", "system:authenticated", "system:serviceaccounts", ] bootstrapUser = ( "system:serviceaccount:openshift-machine-config-operator:node-bootstrapper" ) nodeGroups = ["system:nodes", "system:authenticated"] nodeUser = "******" for csrName in csrList: # Initialize variables csrType, dnsName, ip = None, None, None nodeUserValidation = False bootstrapUserValidation = False # obtain the body of the CSR we want to sign body = certs_api.read_certificate_signing_request_status(csrName) # Decode base64 string to pem format csr decodedCertificate = base64.b64decode( body.spec.request).decode("utf-8") # Load pem format csr try: certificate = cryptography.x509.load_pem_x509_csr( bytes(decodedCertificate, encoding="utf8"), default_backend()) except Exception: print("Error loading CSR") sys.exit(1) if ("bootstrapper" in body.spec.username and "system:node:" not in body.spec.username): groupDifference = set(bootstrapGroups) - set(body.spec.groups) dnsName = certificate.subject.get_attributes_for_oid( cryptography.x509.oid.NameOID.COMMON_NAME)[0].value.split( ":")[2] if (dnsName and body.spec.username == bootstrapUser and len(groupDifference) == 0): csrType = "bootstrapper" bootstrapUserValidation = True elif ("bootstrapper" not in body.spec.username and "system:node:" in body.spec.username): groupDifference = set(nodeGroups) - set(body.spec.groups) crt_san_data = certificate.extensions.get_extension_for_oid( cryptography.x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME) dnsName = crt_san_data.value.get_values_for_type( cryptography.x509.DNSName)[0] ip = crt_san_data.value.get_values_for_type( cryptography.x509.IPAddress)[0] if (dnsName and body.spec.username == nodeUser + dnsName and len(groupDifference) == 0): csrType = "node" nodeUserValidation = True else: print("Unknown CSR type") sys.exit(1) if (csrType == "node" and next( (item for item in nodeInfoList if item["node"] == dnsName), None) and next( (item for item in nodeInfoList if item["ip"] == str(ip)), None) and nodeUserValidation) or (csrType == "bootstrapper" and next( (item for item in nodeInfoList if item["node"] == dnsName), None) and bootstrapUserValidation): # create an approval condition approval_condition = client.V1beta1CertificateSigningRequestCondition( last_update_time=datetime.now(timezone.utc).astimezone(), message= "This certificate was approved by CSR Approval Operator", reason="Validated and approved by CSR Approval Operator", type="Approved", ) # patch the existing `body` with the new conditions # you might want to append the new conditions to the existing ones body.status.conditions = [approval_condition] # patch the Kubernetes object response = certs_api.replace_certificate_signing_request_approval( csrName, body) # Increase count of approvedCSRCount variable approvedCSRs.append(csrName) if csrType == "node" and any("label" in d for d in nodeInfoList if d["node"] == dnsName): approvedNodesToLabel.append({ "node": dnsName, "label": "".join([ d["label"] for d in nodeInfoList if d["node"] == dnsName ]), }) approvedNodes.append(dnsName) if csrType == "node" and any("taint" in d for d in nodeInfoList if d["node"] == dnsName): approvedNodesToTaint.append({ "node": dnsName, "taint": "".join([ d["taint"] for d in nodeInfoList if d["node"] == dnsName ]), }) approvedNodes.append(dnsName) if csrType == "node" and not any("label" in d for d in nodeInfoList if d["node"] == dnsName): approvedNodes.append(dnsName) if csrType == "bootstrapper": approvedBootStrappedNodes.append(dnsName) approvedNodes = list(dict.fromkeys(approvedNodes)) return ( approvedNodes, approvedCSRs, approvedNodesToLabel, approvedBootStrappedNodes, approvedNodesToTaint, )
def init_tls_pair(namespace): """Function to load or create tls for admission webhook""" tls_pair = "" logging.info("Starting TLS init process") # Check if custom secret was specified in ENV vars magtape_tls_secret_name = os.getenv("magtape_tls_secret_name", magtape_tls_pair_secret_name) if magtape_tls_secret_name != magtape_tls_pair_secret_name: logging.debug("Magtape TLS Secret specified") try: config.load_incluster_config() except Exception as exception: logging.info( f"Exception loading in-cluster configuration: {exception}") try: logging.info("Loading local kubeconfig") config.load_kube_config() except Exception as exception: logging.error(f"Exception loading local kubeconfig: {exception}") sys.exit(1) configuration = client.Configuration() core_api = client.CoreV1Api(client.ApiClient(configuration)) certificates_api = client.CertificatesV1beta1Api( client.ApiClient(configuration)) # Read existing secret tls_secret, tls_pair, secret_exists, magtape_tls_byoc = read_tls_pair( namespace, magtape_tls_pair_secret_name, tls_pair, core_api) if secret_exists: logging.info("Existing TLS cert and key found") # Check if cert should be updated secret_should_update = cert_should_update(namespace, secret_exists, tls_secret, magtape_tls_byoc) if secret_should_update: if magtape_tls_byoc: logging.warning( f"WARN - Certificate used for Admission Webhook is past threshhold for normal rotation. Not rotating because this cert isn't managed by the K8s CA" ) else: logging.info(f"Generating new cert/key pair for TLS") # Generate TLS Pair tls_pair = build_tls_pair( namespace, magtape_tls_pair_secret_name, magtape_service_name, certificates_api, ) # Handle cert creation or update write_tls_pair( namespace, magtape_tls_secret_name, secret_exists, secret_should_update, tls_secret, tls_pair, magtape_tls_byoc, core_api, )
logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) formatter = TextFormatter(datefmt="Z", colorize=True) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) ch.setFormatter(formatter) logger.addHandler(ch) config.load_kube_config() corev1_api = client.CoreV1Api(client.ApiClient()) apps_v1_api = client.AppsV1Api(client.ApiClient()) webhook_api = client.AdmissionregistrationV1beta1Api(client.ApiClient()) cert_api = client.CertificatesV1beta1Api(client.ApiClient()) APP_NAME = "maglev-admission-webhook" SECRET = "shhhh!donottell" NAMESPACE = "default" CSR_NAME = "{}.{}".format(APP_NAME, NAMESPACE) IMAGE = "harshanarayana/sanic-webhook:v0.2" TEMPLATE_ENV = Environment(loader=BaseLoader) RESOURCE_CREATION_MAP = { "Deployment": { "handler": apps_v1_api.create_namespaced_deployment }, "Service": { "handler": corev1_api.create_namespaced_service },
def __init__(self): self.core = client.CoreV1Api() self.certs = client.CertificatesV1beta1Api() self.rbac = client.RbacAuthorizationV1Api() self.settings_api = client.SettingsV1alpha1Api() self.policy = client.PolicyV1beta1Api()
from OpenSSL.crypto import FILETYPE_PEM, load_certificate_request import yaml from kubernetes import client, config, watch import os import re if __name__ == "__main__": if 'KUBERNETES_PORT' in os.environ: config.load_incluster_config() else: config.load_kube_config() configuration = client.Configuration() configuration.assert_hostname = False api_client = client.api_client.ApiClient(configuration=configuration) v1 = client.CoreV1Api() certs_api = client.CertificatesV1beta1Api() try: k8sfile = '/var/run/secrets/kubernetes.io/serviceaccount/namespace' namespace = open(k8sfile, 'r').read() if os.path.exists( k8sfile) else os.environ.get('NAMESPACE', 'default') config_map_name = os.environ.get('CONFIG_MAP', 'autorules') config_map = v1.read_namespaced_config_map(namespace=namespace, name=config_map_name) config_map_data = config_map.to_dict().get('data', {}) except Exception as e: if e.status == 404: print("Missing configmap %s in namespace %s" % (config_map_name, namespace)) config_map_data = {} else: print(e)
"Certificate {} was approved.".format(metadata_name)) except ApiException as e: logger.warning( "Exception when calling Certificatesapi_clientbeta1Api->replace_certificate_signing_request_approval: %s\n" % e) else: logger.info( "Certificate was already approved {}".format(metadata_name)) if __name__ == "__main__": if 'CLUSTER' in os.environ: config.load_incluster_config() else: config.load_kube_config() api_client = client.CertificatesV1beta1Api() w = watch.Watch() for event in w.stream(api_client.list_certificate_signing_request, watch=True): if event["type"] not in "DELETED": certificate = event["object"] try: metadata_name = event["object"].metadata.name spec_groups = event["object"].spec.groups spec_username = event["object"].spec.username logger.info("Handling {} on {}".format(event["type"], metadata_name)) approve_certificate(api_client, certificate, spec_username, spec_groups, metadata_name) except: logger.warning("{} Can't handle certificate".format(