使用k8s給你的服務簽發證書

使用場景

當咱們須要進行服務端認證,甚至雙向認證時,咱們須要生成密鑰對和服務信息,並使用ca對公鑰和服務信息進行批准簽發,生成一個證書。node

咱們簡單描述下單向認證和雙向認證的場景流程git

在單向認證場景中:web

  • 服務端會將本身的證書和公鑰告知客戶端
  • 客戶端向CA查詢該證書的合法性,確認合法後會記錄服務端公鑰
  • 客戶端會與服務端明文通訊確認加密方式,
  • 客戶端確認加密方式後,會生成隨機碼做爲對稱加密密鑰,以服務端的公鑰對對稱加密密鑰進行加密,告知服務端,
  • 服務端以本身的私鑰解密獲得對稱加密密鑰,
  • 以後, 客戶端與服務端之間使用對稱加密密鑰進行加密通訊。

在雙向認證的場景中:算法

  • 服務端會將本身的證書和公鑰告知客戶端
  • 客戶端向CA查詢該證書的合法性,確認合法後會記錄服務端公鑰
  • 客戶端會將本身的證書和公鑰發給服務端,
  • 服務端發現客戶端的證書也能夠經過CA認證,則服務端會記錄客戶端的公鑰
  • 而後客戶端會與服務端明文通訊確認加密方式,
  • 但服務端會用客戶端的公鑰將加密方式進行加密
  • 客戶端使用本身的私鑰解密獲得加密方式,會生成隨機碼做爲對稱加密密鑰,以服務端的公鑰對對稱加密密鑰進行加密,告知服務端,
  • 服務端以本身的私鑰解密獲得對稱加密密鑰,
  • 以後, 客戶端與服務端之間使用對稱加密密鑰進行加密通訊。

那麼,咱們若是要開放本身的https服務,或者給kubelet建立可用的客戶端證書,就須要:json

  • 生成密鑰對
  • 生成使用方的信息
  • 使用ca對使用方的公鑰和其餘信息進行審覈,簽發,生成一個使用方證書。

這裏使用方能夠是客戶端(kubelet)或服務端(好比一個咱們本身開發的webhook server)api

手動簽發證書

k8s集羣部署時會自動生成一個CA(證書認證機構),固然這個CA是咱們自動生成的,並不具備任何合法性。k8s還提供了一套api,用於對用戶自主建立的證書進行認證簽發。服務器

準備

  • 安裝k8s集羣
  • 安裝cfssl工具,從這裏下載cfssl和cfssljson

建立你的證書

執行下面的命令,生成server.csr和server-key.pem。app

cat <<EOF | cfssl genkey - | cfssljson -bare server
{
  "hosts": [
    "my-svc.my-namespace.svc.cluster.local",
    "my-pod.my-namespace.pod.cluster.local",
    "192.0.2.24",
    "10.0.34.2"
  ],
  "CN": "kubernetes",
  "key": {
    "algo": "ecdsa",
    "size": 256
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

這裏你能夠修改文件裏的內容,主要是:工具

  • hosts。 服務地址,你能夠填入service的域名,service的clusterIP,podIP等等
  • CN 。對於 SSL 證書,通常爲網站域名;而對於代碼簽名證書則爲申請單位名稱;而對於客戶端證書則爲證書申請者的姓名.k8s會將CN的內容視爲正式使用者的User Name
  • key。加密算法和長度。通常有ecdsa算法和rsa算法,rsa算法的size通常是2048或1024
  • names。證書申請者的信息,好比位置、組織等。k8s的RBAC會將證書中的O視爲證書使用者所在的Group

這一步生成的server-key.pem是服務端的私鑰,而server.csr則含有公鑰、組織信息、我的信息(域名)。jsonp

建立一個CSR資源

執行以下腳本:

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: my-svc.my-namespace
spec:
  request: $(cat server.csr | base64 | tr -d '\n')
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

在k8s集羣中建立一個csr資源。注意要將第一步中建立的server.csr內容進行base64編碼,去掉換行後填入spec.request中。spec.usages中填入咱們對證書的要求,包括數字簽名、密鑰加密、服務器驗證。通常填這三個就夠了。

以後咱們經過kubectl describe csr my-svc.my-namespace 能夠看到:

Name:                   my-svc.my-namespace
Labels:                 <none>
Annotations:            <none>
CreationTimestamp:      Tue, 21 Mar 2017 07:03:51 -0700
Requesting User:        yourname@example.com
Status:                 Pending
Subject:
        Common Name:    my-svc.my-namespace.svc.cluster.local
        Serial Number:
Subject Alternative Names:
        DNS Names:      my-svc.my-namespace.svc.cluster.local
        IP Addresses:   192.0.2.24
                        10.0.34.2
Events: <none>

認證csr

注意到,csr的status是pending,說明尚未被CA認證。在k8s集羣中,若是是node上kubelet建立的CSR,kube-controller-manager會自動進行認證,而咱們手動建立的證書,須要進行手動認證:
kubectl certificate approve

也能夠拒絕:kubectl certificate deny

以後咱們再檢查csr,發現已是approved了:

kubectl get csr
NAME                  AGE       REQUESTOR               CONDITION
my-svc.my-namespace   10m       yourname@example.com    Approved,Issued

咱們能夠經過

kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}' | base64 --decode > server.crt

命令,獲得server的證書。以後你就可使用server.crt和server-key.pem做爲你的服務的https認證

流程總結

  1. 編寫一個json文件,描述server的信息,包括域名(或IP),CN,加密方式
  2. 執行cfssl命令生成server的密鑰,和認證請求文件server.csr
  3. 將server.csr內容編碼,在k8s中建立一個server的CSR資源
  4. 手動對該CSR資源進行認證簽發
  5. 將k8s生成的server.crt 即服務端證書拷貝下來。
  6. server.crt 和server-key.pem 即server的https服務配置

參考: https://kubernetes.io/docs/ta...

相關文章
相關標籤/搜索