使用 Python 客户端在 Kubernetes 中批准 CSR

Approve a CSR in Kuberentes Using the Python client

我在 Kubernetes 中有以下 CSR 对象:

$ kubectl get csr
NAME                                     AGE       REQUESTOR                                      CONDITION
test-certificate-0.my-namespace          53m       system:serviceaccount:my-namespace:some-user   Pending

我想使用 Python API 客户端批准它:

from kuberentes import config, client
# configure session
config.load_kube_config()
# get a hold of the certs API
certs_api = client.CertificatesV1beta1Api()

# read my CSR
csr = certs_api.read_certificate_signing_request("test-certificate-0.my-namespace")

现在,csr对象的内容是:

{'api_version': 'certificates.k8s.io/v1beta1',
 'kind': 'CertificateSigningRequest',
 'metadata': {'annotations': None,
              'cluster_name': None,
              'creation_timestamp': datetime.datetime(2019, 3, 15, 14, 36, 28, tzinfo=tzutc()),
              'deletion_grace_period_seconds': None,
              'name': 'test-certificate-0.my-namespace',
              'namespace': None,
              'owner_references': None,
              'resource_version': '4269575',
              'self_link': '/apis/certificates.k8s.io/v1beta1/certificatesigningrequests/test-certificate-0.my-namespace',
              'uid': 'b818fa4e-472f-11e9-a394-124b379b4e12'},
 'spec': {'extra': None,
          'groups': ['system:serviceaccounts',
                     'system:serviceaccounts:cloudp-38483-test01',
                     'system:authenticated'],
          'request': 'redacted',
          'uid': 'd5bfde1b-4036-11e9-a394-124b379b4e12',
          'usages': ['digital signature', 'key encipherment', 'server auth'],
          'username': 'system:serviceaccount:test-certificate-0.my-namespace'},
 'status': {'certificate': 'redacted',
            'conditions': [{'last_update_time': datetime.datetime(2019, 3, 15, 15, 13, 32, tzinfo=tzutc()),
                            'message': 'This CSR was approved by kubectl certificate approve.',
                            'reason': 'KubectlApprove',
                            'type': 'Approved'}]}}

我想以编程方式批准这个证书,如果我使用 kubectl 来完成它(-v=10 将使 kubectl 输出 http 流量) :

kubectl certificate approve test-certificate-0.my-namespace -v=10

我看到 PUT 操作用于批准 我的证书:

PUT https://my-kubernetes-cluster.com:8443/apis/certificates.k8s.io/v1beta1/certificatesigningrequests/test-certificate-0.my-namespace/approval

所以我需要PUT到证书对象的/approval资源。现在,我该如何使用 Python Kubernetes 客户端?

它的名字很奇怪,但它在 python 客户端的 docs 中 - 你想要 replace_certificate_signing_request_approval

# create an instance of the API class
api_instance = kubernetes.client.CertificatesV1beta1Api(kubernetes.client.ApiClient(configuration))
name = 'name_example' # str | name of the CertificateSigningRequest
body = kubernetes.client.V1beta1CertificateSigningRequest() # V1beta1CertificateSigningRequest | 
dry_run = 'dry_run_example' # str | When present, indicates that modifications should not be persisted. An invalid or unrecognized dryRun directive will result in an error response and no further processing of the request. Valid values are: - All: all dry run stages will be processed (optional)
pretty = 'pretty_example' # str | If 'true', then the output is pretty printed. (optional)

try: 
    api_response = api_instance.replace_certificate_signing_request_approval(name, body, dry_run=dry_run, pretty=pretty)
    pprint(api_response)
except ApiException as e:
    print("Exception when calling CertificatesV1beta1Api->replace_certificate_signing_request_approval: %s\n" % e)

根据@jaxxstorm 的回答和我自己的调查来回答我的问题:

# Import required libs and configure your client
from datetime import datetime, timezone
from kubernetes import config, client
config.load_kube_config()

# this is the name of the CSR we want to Approve
name = 'my-csr'

# a reference to the API we'll use 
certs_api = client.CertificatesV1beta1Api()

# obtain the body of the CSR we want to sign
body = certs_api.read_certificate_signing_request_status(name)

# create an approval condition
approval_condition = client.V1beta1CertificateSigningRequestCondition(
    last_update_time=datetime.now(timezone.utc).astimezone(),
    message='This certificate was approved by Python Client API',
    reason='MyOwnReason',
    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(name, body)

在此之后,KubeCA 将批准并颁发新证书。颁发的证书文件可以从我们刚刚得到的response对象中获取:

import base64
base64.b64decode(response.status.certificate) # this will return the decoded cert