def load_gke_config(fname: Filepath, context: Optional[str], disable_warnings: bool = False) -> Tuple[K8sConfig, bool]: """Return K8s access config for GKE cluster described in `kubeconfig`. Returns None if `kubeconfig` does not exist or could not be parsed. Inputs: kubconfig: str Name of kubeconfig file. context: str Kubeconf context. Use `None` to use default context. disable_warnings: bool Whether or not do disable GCloud warnings. Returns: Config """ # Parse the kubeconfig file. name, user, cluster, err = load_kubeconfig(fname, context) if err: return (K8sConfig(), True) # Unpack the self signed certificate (Google does not register the K8s API # server certificate with a public CA). try: ssl_ca_cert_data = base64.b64decode( cluster["certificate-authority-data"]) except KeyError: logit.debug(f"Context {context} in <{fname}> is not a GKE config") return (K8sConfig(), True) # Save the certificate to a temporary file. This is only necessary because # the requests library will need a path to the CA file - unfortunately, we # cannot just pass it the content. _, tmp = tempfile.mkstemp(text=False) ssl_ca_cert = Filepath(tmp) ssl_ca_cert.write_bytes(ssl_ca_cert_data) with warnings.catch_warnings(record=disable_warnings): try: cred, project_id = google.auth.default( scopes=['https://www.googleapis.com/auth/cloud-platform']) cred.refresh(google.auth.transport.requests.Request()) token = cred.token except google.auth.exceptions.DefaultCredentialsError as e: logit.error(str(e)) return (K8sConfig(), True) # Return the config data. logit.info("Assuming GKE cluster.") return K8sConfig( url=cluster["server"], token=token, ca_cert=ssl_ca_cert, client_cert=None, version="", name=cluster["name"], ), False
def load_eks_config(fname: Filepath, context: Optional[str], disable_warnings: bool = False) -> Tuple[K8sConfig, bool]: """Return K8s access config for EKS cluster described in `kubeconfig`. Returns None if `kubeconfig` does not exist or could not be parsed. Inputs: fname: Filepath Kubeconfig file. context: str Kubeconf context. Use `None` to use default context. disable_warnings: bool Whether or not do disable GCloud warnings. Returns: Config """ # Parse the kubeconfig file. name, user, cluster, err = load_kubeconfig(fname, context) if err: return (K8sConfig(), True) # Get a copy of all env vars. We will pass that one along to the # sub-process, plus the env vars specified in the kubeconfig file. env = os.environ.copy() # Unpack the self signed certificate (AWS does not register the K8s API # server certificate with a public CA). try: ssl_ca_cert_data = base64.b64decode( cluster["certificate-authority-data"]) cmd = user["exec"]["command"] args = user["exec"]["args"] env_kubeconf = user["exec"].get("env", []) except KeyError: logit.debug(f"Context {context} in <{fname}> is not an EKS config") return (K8sConfig(), True) # Convert a None value (valid value in YAML) to an empty list of env vars. env_kubeconf = env_kubeconf if env_kubeconf else [] # Save the certificate to a temporary file. This is only necessary because # the Requests library will need a path to the CA file - unfortunately, we # cannot just pass it the content. _, tmp = tempfile.mkstemp(text=False) ssl_ca_cert = Filepath(tmp) ssl_ca_cert.write_bytes(ssl_ca_cert_data) # Compile the name, arguments and env vars for the command specified in kubeconf. cmd_args = [cmd] + args env_kubeconf = {_["name"]: _["value"] for _ in env_kubeconf} env.update(env_kubeconf) logit.debug( f"Requesting EKS certificate: {cmd_args} with envs: {env_kubeconf}") # Pre-format the command for the log message. log_cmd = (f"kubeconf={fname} kubectx={context} " f"cmd={cmd_args} env={env_kubeconf}") # Run the specified command to produce the access token. That program must # produce a YAML document on stdout that specifies the bearer token. try: out = subprocess.run(cmd_args, stdout=subprocess.PIPE, env=env) token = yaml.safe_load(out.stdout.decode("utf8"))["status"]["token"] except FileNotFoundError: logit.error( f"Could not find {cmd} application to get token ({log_cmd})") return (K8sConfig(), True) except (KeyError, yaml.YAMLError): logit.error( f"Token manifest produce by {cmd_args} is corrupt ({log_cmd})") return (K8sConfig(), True) except TypeError: logit.error( f"The YAML token produced by {cmd_args} is corrupt ({log_cmd})") return (K8sConfig(), True) # Return the config data. logit.info("Assuming EKS cluster.") return K8sConfig( url=cluster["server"], token=token, ca_cert=ssl_ca_cert, client_cert=None, version="", name=cluster["name"], ), False