没错,发布后
在本教程中,我们将逐步创建
查看
如果我们去
图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 机器人。 如何简化自己和他人的生活
来源: habr.com