沒錯,發布後
在本教程中,我們將逐步創建
Обзор
如果我們去
圖1:Consul授權方式官方概述
讓我們看看
當然,那裡有有用的信息,但沒有關於如何實際使用它們的指南。 因此,像任何理智的人一樣,您會在網路上搜尋指導。 然後...你失敗了。 它發生了。 讓我們解決這個問題。
在繼續創建 POC 之前,我們先回顧一下 Consul 的授權方法(圖 1),並在 Kubernetes 的背景下對其進行完善。
架構
在本教程中,我們將在一台單獨的電腦上建立一個 Consul 伺服器,該伺服器將與安裝了 Consul 用戶端的 Kubernetes 叢集進行通訊。 然後,我們將在 Pod 中建立虛擬應用程序,並使用我們配置的授權方法從 Consul 鍵/值儲存中讀取資料。
下圖詳細介紹了我們在本教程中創建的架構,以及授權方法背後的邏輯,稍後將對此進行解釋。
圖2:Kubernetes授權方式概述
快速說明:Consul 伺服器不需要位於 Kubernetes 叢集之外才能運作。 但是,是的,他可以這樣那樣做。
因此,將 Consul 概覽圖(圖 1)應用在 Kubernetes 上,我們得到上面的圖(圖 2),這裡的邏輯如下:
- 每個 Pod 都會附加一個服務帳戶,其中包含 Kubernetes 產生和已知的 JWT 令牌。 預設情況下,此令牌也會插入到 pod 中。
- Pod 內的應用程式或服務向我們的 Consul 用戶端發起登入命令。 登入請求還將包括我們的令牌和名稱 專門創造的 授權方法(Kubernetes 類型)。 此步驟 #2 對應於 Consul 圖(方案 1)的步驟 1。
- 然後,我們的 Consul 用戶端會將這個請求轉送到我們的 Consul 伺服器。
- 魔法! Consul 伺服器在此驗證請求的真實性、收集有關請求身分的資訊並將其與任何關聯的預定義規則進行比較。 下面是另一個圖來說明這一點。 此步驟對應於 Consul 概覽圖(圖 3)的步驟 4、5 和 1。
- 我們的 Consul 伺服器根據我們指定的有關請求者身分的授權方法規則(我們已經定義)產生具有權限的 Consul 令牌。 然後它將將該令牌發回。 這對應於 Consul 圖(圖 6)的步驟 1。
- 我們的 Consul 用戶端將令牌轉發給請求的應用程式或服務。
我們的應用程式或服務現在可以使用此 Consul 令牌與我們的 Consul 資料進行通信,具體取決於令牌的權限。
魔法揭曉了!
對於那些不滿足於只是從帽子裡跳出來的兔子並想知道它是如何工作的人......讓我“告訴你有多深” 兔子洞“。
如前所述,我們的「神奇」步驟(圖 2:步驟 4)是 Consul 伺服器對請求進行身份驗證、收集有關請求的資訊並將其與任何關聯的預定義規則進行比較。 此步驟對應於 Consul 概覽圖(圖 3)的步驟 4、5 和 1。 下面是一個圖(圖3),其目的是清楚顯示實際發生的情況 在引擎蓋下 具體的Kubernetes授權方法。
圖3:魔法揭曉!
- 作為起點,我們的 Consul 用戶端使用 Kubernetes 帳戶令牌和先前建立的授權方法的特定實例名稱將登入請求轉發到我們的 Consul 伺服器。 此步驟對應於前面電路說明中的步驟3。
- 現在Consul伺服器(或領導者)需要驗證接收到的令牌的真實性。 因此,它將諮詢 Kubernetes 叢集(透過 Consul 用戶端),並透過適當的權限,我們將找出代幣是否真實以及它屬於誰。
- 然後,驗證後的請求傳回給Consul領導者,Consul伺服器從登入請求(和Kubernetes類型)中尋找具有指定名稱的授權方法實例。
- 領事領導者識別指定的授權方法實例(如果找到)並讀取附加到它的綁定規則集。 然後它讀取這些規則並將它們與經過驗證的身份屬性進行比較。
- 達-達! 讓我們繼續前面電路說明中的步驟 5。
在常規虛擬機器上執行 Consul-server
從現在開始,我將主要提供有關如何創建此 POC 的說明,通常是要點,而不是完整的句子解釋。 另外,如前所述,我將使用 GCP 創建所有基礎設施,但您可以在其他任何地方創建相同的基礎設施。
- 啟動虛擬機器(實例/伺服器)。
- 為防火牆(AWS 中的安全群組)建立規則:
- 我喜歡為規則和網路標記分配相同的電腦名稱,在本例中為“skywiz-consul-server-poc”。
- 找到本機電腦的 IP 位址並將其新增至來源 IP 位址清單中,以便我們可以存取使用者介面 (UI)。
- 為 UI 開啟連接埠 8500。 按一下“建立”。 我們很快就會再次更改此防火牆[
鏈接 ]. - 在實例中新增防火牆規則。 返回 Consul Server 上的 VM 儀表板,並將「skywiz-consul-server-poc」新增至網路標籤欄位。 點選“儲存”。
- 在虛擬機器上安裝Consul,查看這裡。 請記住,您需要 Consul 版本 ≥ 1.5 [連結]
- 讓我們建立一個單節點Consul - 配置如下。
groupadd --system consul
useradd -s /sbin/nologin --system -g consul consul
mkdir -p /var/lib/consul
chown -R consul:consul /var/lib/consul
chmod -R 775 /var/lib/consul
mkdir /etc/consul.d
chown -R consul:consul /etc/consul.d
### /etc/consul.d/agent.json
{
"acl" : {
"enabled": true,
"default_policy": "deny",
"enable_token_persistence": true
}
}
- 啟動我們的領事伺服器:
consul agent
-server
-ui
-client 0.0.0.0
-data-dir=/var/lib/consul
-bootstrap-expect=1
-config-dir=/etc/consul.d
- 您應該會看到一堆輸出,並以「...更新被 ACL 阻止」結束。
- 尋找 Consul 伺服器的外部 IP 位址,並在連接埠 8500 上使用該 IP 位址開啟瀏覽器。確保 UI 開啟。
- 嘗試新增鍵/值對。 肯定弄錯了。 這是因為我們向 Consul 伺服器載入了 ACL 並禁用了所有規則。
- 返回 Consul 伺服器上的 shell,在背景啟動該進程或以其他方式運行它,然後輸入以下內容:
consul acl bootstrap
- 找到“SecretID”值並返回 UI。 在 ACL 標籤中,輸入剛複製的令牌的機密 ID。 將 SecretID 複製到其他地方,我們稍後會需要它。
- 現在新增鍵/值對。 對於此 POC,請添加以下內容:鍵:“custom-ns/test_key”,值:“我位於 custom-ns 資料夾中!”
使用 Consul 客戶端作為 Daemonset 為我們的應用程式啟動 Kubernetes 集群
- 建立 K8s (Kubernetes) 叢集。 我們將其建立在與伺服器相同的區域中,以便更快訪問,因此我們可以使用相同的子網路輕鬆連接內部 IP 位址。 我們稱之為“skywiz-app-with-consul-client-poc”。
- 附帶說明一下,這是我在使用 Consul Connect 設定 POC Consul 叢集時遇到的一個很好的教學。
- 我們還將使用帶有擴展值檔案的 Hashicorp helm 圖表。
- 安裝並配置 Helm。 設定步驟:
kubectl create serviceaccount tiller --namespace kube-system
kubectl create clusterrolebinding tiller-admin-binding
--clusterrole=cluster-admin --serviceaccount=kube-system:tiller
./helm init --service-account=tiller
./helm update
- 舵圖:
https://www.consul.io/docs/platform/k8s/helm.html - 使用以下值檔案(注意我已經禁用了大部分):
### poc-helm-consul-values.yaml
global:
enabled: false
image: "consul:latest"
# Expose the Consul UI through this LoadBalancer
ui:
enabled: false
# Allow Consul to inject the Connect proxy into Kubernetes containers
connectInject:
enabled: false
# Configure a Consul client on Kubernetes nodes. GRPC listener is required for Connect.
client:
enabled: true
join: ["<PRIVATE_IP_CONSUL_SERVER>"]
extraConfig: |
{
"acl" : {
"enabled": true,
"default_policy": "deny",
"enable_token_persistence": true
}
}
# Minimal Consul configuration. Not suitable for production.
server:
enabled: false
# Sync Kubernetes and Consul services
syncCatalog:
enabled: false
- 應用舵圖:
./helm install -f poc-helm-consul-values.yaml ./consul-helm - name skywiz-app-with-consul-client-poc
- 當它嘗試運行時,它將需要 Consul 伺服器的權限,所以讓我們添加它們。
- 請注意叢集儀表板上的“Pod 位址範圍”,並參考我們的“skywiz-consul-server-poc”防火牆規則。
- 將 Pod 的位址範圍新增至 IP 位址清單中,並開啟連接埠 8301 和 8300。
- 前往 Consul UI,幾分鐘後您將看到我們的叢集出現在節點標籤中。
Consul與Kubernetes整合設定授權方式
- 返回Consul伺服器shell並導出先前儲存的令牌:
export CONSUL_HTTP_TOKEN=<SecretID>
- 我們需要來自 Kubernetes 叢集的資訊來建立 auth 方法的實例:
- kubernetes 主機
kubectl get endpoints | grep kubernetes
- kubernetes-服務帳戶-jwt
kubectl get sa <helm_deployment_name>-consul-client -o yaml | grep "- name:"
kubectl get secret <secret_name_from_prev_command> -o yaml | grep token:
- 該令牌是 Base64 編碼的,因此請使用您最喜歡的工具對其進行解密[
鏈接 ] - kubernetes-ca-證書
kubectl get secret <secret_name_from_prev_command> -o yaml | grep ca.crt:
- 取得「ca.crt」證書(經過base64解碼後)並將其寫入「ca.crt」檔案中。
- 現在實例化 auth 方法,將佔位符替換為您剛剛收到的值。
consul acl auth-method create
-type "kubernetes"
-name "auth-method-skywiz-consul-poc"
-description "This is an auth method using kubernetes for the cluster skywiz-app-with-consul-client-poc"
-kubernetes-host "<k8s_endpoint_retrieved earlier>"
[email protected]
-kubernetes-service-account-
jwt="<decoded_token_retrieved_earlier>"
- 接下來我們需要建立一條規則並將其附加到新角色。 對於這部分,您可以使用 Consul UI,但我們將使用命令列。
- 寫一條規則
### kv-custom-ns-policy.hcl
key_prefix "custom-ns/" {
policy = "write"
}
- 應用規則
consul acl policy create
-name kv-custom-ns-policy
-description "This is an example policy for kv at custom-ns/"
-rules @kv-custom-ns-policy.hcl
- 從輸出中尋找您剛剛建立的規則的 ID。
- 使用新規則建立角色。
consul acl role create
-name "custom-ns-role"
-description "This is an example role for custom-ns namespace"
-policy-id <policy_id>
- 現在我們將新角色與 auth 方法實例相關聯。 請注意,「選擇器」標誌確定我們的登入請求是否將接收此角色。 在此處檢查其他選擇器選項:
https://www.consul.io/docs/acl/auth-methods/kubernetes.html#trusted-identity-attributes
consul acl binding-rule create
-method=auth-method-skywiz-consul-poc
-bind-type=role
-bind-name='custom-ns-role'
-selector='serviceaccount.namespace=="custom-ns"'
最後配置
訪問權
- 建立存取權限。 我們需要授予 Consul 權限來驗證和識別 K8s 服務帳戶代幣的身份。
- 將以下內容寫入文件中
[關聯] :
###skywiz-poc-consul-server_rbac.yaml
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: review-tokens
namespace: default
subjects:
- kind: ServiceAccount
name: skywiz-app-with-consul-client-poc-consul-client
namespace: default
roleRef:
kind: ClusterRole
name: system:auth-delegator
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: service-account-getter
namespace: default
rules:
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: get-service-accounts
namespace: default
subjects:
- kind: ServiceAccount
name: skywiz-app-with-consul-client-poc-consul-client
namespace: default
roleRef:
kind: ClusterRole
name: service-account-getter
apiGroup: rbac.authorization.k8s.io
- 讓我們建立存取權限
kubectl create -f skywiz-poc-consul-server_rbac.yaml
連接到 Consul 用戶端
### poc-consul-client-ds-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: consul-ds-client
spec:
selector:
app: consul
chart: consul-helm
component: client
hasDNS: "true"
release: skywiz-app-with-consul-client-poc
ports:
- protocol: TCP
port: 80
targetPort: 8500
- 然後使用以下內建指令建立一個 configmap [
鏈接 ]。 請注意,我們指的是我們的服務名稱,如有必要請更換它。
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
labels:
addonmanager.kubernetes.io/mode: EnsureExists
name: kube-dns
namespace: kube-system
data:
stubDomains: |
{"consul": ["$(kubectl get svc consul-ds-client -o jsonpath='{.spec.clusterIP}')"]}
EOF
測試 auth 方法
現在讓我們來看看魔術的實際效果吧!
- 使用相同的頂級密鑰建立多個密鑰資料夾(即/sample_key) 和您選擇的值。 為新的關鍵路徑創建適當的政策和角色。 我們稍後會進行綁定。
自訂命名空間測試:
- 讓我們創造自己的命名空間:
kubectl create namespace custom-ns
- 讓我們在新的命名空間中建立一個 pod。 編寫 Pod 的配置。
###poc-ubuntu-custom-ns.yaml
apiVersion: v1
kind: Pod
metadata:
name: poc-ubuntu-custom-ns
namespace: custom-ns
spec:
containers:
- name: poc-ubuntu-custom-ns
image: ubuntu
command: ["/bin/bash", "-ec", "sleep infinity"]
restartPolicy: Never
- 創建於:
kubectl create -f poc-ubuntu-custom-ns.yaml
- 容器運行後,轉到那裡並安裝curl。
kubectl exec poc-ubuntu-custom-ns -n custom-ns -it /bin/bash
apt-get update && apt-get install curl -y
- 現在我們將使用我們先前建立的授權方法向Consul發送登入請求[
鏈接 ]. - 若要從您的服務帳戶查看輸入的令牌:
cat /run/secrets/kubernetes.io/serviceaccount/token
- 將以下內容寫入容器內的文件中:
### payload.json
{
"AuthMethod": "auth-method-test",
"BearerToken": "<jwt_token>"
}
- 登入!
curl
--request POST
--data @payload.json
consul-ds-client.default.svc.cluster.local/v1/acl/login
- 要在一行中完成上述步驟(因為我們將執行多個測試),您可以執行以下操作:
echo "{
"AuthMethod": "auth-method-skywiz-consul-poc",
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)"
}"
| curl
--request POST
--data @-
consul-ds-client.default.svc.cluster.local/v1/acl/login
- 作品! 至少應該是如此。 現在取得 SecretID 並嘗試存取我們應該有權存取的鍵/值。
curl
consul-ds-client.default.svc.cluster.local/v1/kv/custom-ns/test_key --header “X-Consul-Token: <SecretID_from_prev_response>”
- 您可以對「Value」進行 Base64 解碼,並查看它是否與 UI 中的 custom-ns/test_key 中的值相符。 如果您在本教程中使用與上面相同的值,則您的編碼值將為 IkknbSBpbiB0aGUgY3VzdG9tLW5zIGZvbGRlciEi。
用戶服務帳戶測試:
- 使用以下命令建立自訂 ServiceAccount [
鏈接 ].
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: custom-sa
EOF
- 為 Pod 建立一個新的設定檔。 請注意,我包含了curl 安裝以節省勞動力:)
###poc-ubuntu-custom-sa.yaml
apiVersion: v1
kind: Pod
metadata:
name: poc-ubuntu-custom-sa
namespace: default
spec:
serviceAccountName: custom-sa
containers:
- name: poc-ubuntu-custom-sa
image: ubuntu
command: ["/bin/bash","-ec"]
args: ["apt-get update && apt-get install curl -y; sleep infinity"]
restartPolicy: Never
- 之後,在容器內執行 shell。
kubectl exec -it poc-ubuntu-custom-sa /bin/bash
- 登入!
echo "{
"AuthMethod": "auth-method-skywiz-consul-poc",
"BearerToken": "$(cat /run/secrets/kubernetes.io/serviceaccount/token)"
}"
| curl
--request POST
--data @-
consul-ds-client.default.svc.cluster.local/v1/acl/login
- 沒有權限。 哦,我們忘記添加與適當權限綁定的新規則,讓我們現在就這樣做。
重複上面的步驟:
a) 為前綴「custom-sa/」建立相同的策略。
b) 創造一個角色,命名為“custom-sa-role”
c) 將策略附加到角色。
- 建立規則綁定(只能透過 cli/api 實現)。 請注意選擇器標誌的不同意義。
consul acl binding-rule create
-method=auth-method-skywiz-consul-poc
-bind-type=role
-bind-name='custom-sa-role'
-selector='serviceaccount.name=="custom-sa"'
- 從“poc-ubuntu-custom-sa”容器再次登入。 成功!
- 查看我們對 custom-sa/ 鍵路徑的存取。
curl
consul-ds-client.default.svc.cluster.local/v1/kv/custom-sa/test_key --header “X-Consul-Token: <SecretID>”
- 您也可以確保此令牌不會授予對「custom-ns/」中的 kv 的存取權。 只需將“custom-sa”替換為前綴“custom-ns”後重複上述命令即可。
沒有權限。
疊加範例:
- 值得注意的是,所有規則綁定映射都會新增到具有這些權限的令牌中。
- 我們的容器“poc-ubuntu-custom-sa”位於預設命名空間中 - 所以讓我們將它用於不同的規則綁定。
- 重複前面的步驟:
a) 為「default/」鍵前綴建立相同的策略。
b) 建立一個角色,將其命名為“default-ns-role”
c) 將策略附加到角色。 - 建立規則綁定(只能透過 cli/api 實現)
consul acl binding-rule create
-method=auth-method-skywiz-consul-poc
-bind-type=role
-bind-name='default-ns-role'
-selector='serviceaccount.namespace=="default"'
- 返回我們的容器“poc-ubuntu-custom-sa”並嘗試訪問“default/”kv 路徑。
- 沒有權限。
您可以在 UI 中的 ACL > 令牌下查看每個令牌的指定憑證。 如您所見,我們目前的令牌僅附加一個“custom-sa-role”。 我們目前使用的令牌是在我們登入時產生的,當時只有一個規則綁定匹配。 我們需要再次登入並使用新令牌。 - 確保您可以從“custom-sa/”和“default/”kv 路徑讀取。
成功了!
這是因為我們的“poc-ubuntu-custom-sa”與“custom-sa”和“default-ns”規則綁定相符。
結論
TTL 令牌管理?
截至撰寫本文時,還沒有整合的方法來確定此授權方法產生的令牌的 TTL。 這將是提供 Consul 授權安全自動化的絕佳機會。
有一個選項可以手動建立帶有 TTL 的令牌:
https://www.consul.io/docs/acl/acl-system.html#acl-tokens
到期時間 - 該令牌將被撤銷的時間。 (可選;在 Consul 1.5.0 中新增)- 僅用於手動建立/更新
https://www.consul.io/api/acl/tokens.html#expirationtime
希望在不久的將來我們能夠控制令牌的產生方式(根據規則或授權方法)並添加 TTL。
在此之前,建議您在邏輯中使用註銷端點。
https://www.consul.io/api/acl/acl.html#logout-from-auth-method https://www.consul.io/docs/acl/acl-auth-methods.html#overall-login-process
也請閱讀我們部落格上的其他文章:
從無授權的ClickHouse遷移到授權的ClickHouse導致了什麼? 如何使用 GitLab CI/CD 運行多個管道 縮小 Docker 映像的三個簡單技巧 Traefik 作為 K8S 的入口控制器 大量異質Web項目的備份 Redmine 的 Telegram 機器人。 如何簡化自己和他人的生活
來源: www.habr.com