webhook应用

明白,你是对 **Group 授权**,而不是单独对 User 授权。下面我帮你详细解释每一步命令的作用,重点突出:

* **为什么要先签证书**(带 Group)
* **如何创建 kubeconfig 使用该证书**
* **RBAC ClusterRoleBinding 里对 Group 授权的意义**
* **验证权限的逻辑**

---

# 1. 生成私钥和 CSR(带 Group 和 User)

```bash
openssl genrsa -out new-admin.key 2048
```

* 作用:生成一个 2048 位的 RSA 私钥,存到文件 `new-admin.key`。
* 私钥是客户端身份的核心,后续用于生成 CSR 和签名请求。

```bash
openssl req -new -key new-admin.key -out new-admin.csr -subj "/O=new-system:masters/CN=new-kubernetes-admin"
```

* 作用:根据私钥 `new-admin.key` 生成一个证书签名请求(CSR),写入 `new-admin.csr`。
* `-subj "/O=new-system:masters/CN=new-kubernetes-admin"` 说明:

* **CN(Common Name)** 是用户名,这里是 `new-kubernetes-admin`。
* **O(Organization)** 是用户组,这里是 `new-system:masters`。
* Kubernetes 的认证逻辑中,`CN` 和 `O` 作为认证身份标识,后续通过 RBAC 授权。
* **重要:只有带 `O=new-system:masters` 的证书,才能匹配你后续 ClusterRoleBinding 中对该组的授权。**

---

# 2. 使用 Kubernetes CA 签发证书

```bash
openssl x509 -req -in new-admin.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial -out new-admin.crt -days 36500 -sha256
```

* 作用:用 Kubernetes 的 CA 对 `new-admin.csr` 证书请求进行签名,生成正式客户端证书 `new-admin.crt`,有效期 365 天。
* 这里的 CA 证书和私钥通常是 Kubernetes 集群初始化时生成的,`apiserver` 会信任由它签发的客户端证书。
* 签发后的证书中会保留 CN 和 O 信息,apiserver 认证时会读取。

---

# 3. 创建 kubeconfig 文件

```bash
kubectl config --kubeconfig=new-admin.kubeconfig set-cluster kubernetes \
--server=https://10.252.176.253:6443 \
--certificate-authority=/etc/kubernetes/pki/ca.crt \
--embed-certs=true
```

* 作用:定义 kubeconfig 文件中的集群信息(名字是 `kubernetes`)。
* `--server` 指定 API Server 地址。
* `--certificate-authority` 指定 CA 证书路径,用于验证 apiserver 的 TLS。
* `--embed-certs=true` 将 CA 证书内容嵌入 kubeconfig 文件,方便携带。

```bash
kubectl config --kubeconfig=new-admin.kubeconfig set-credentials new-kubernetes-admin \
--client-certificate=new-admin.crt \
--client-key=new-admin.key \
--embed-certs=true
```

* 作用:配置 kubeconfig 文件中的用户凭证,指定客户端证书和私钥。
* 用户名是 `new-kubernetes-admin`,和证书 CN 一致。
* 证书和私钥内容会嵌入 kubeconfig 文件。

```bash
kubectl config --kubeconfig=new-admin.kubeconfig set-context new-kubernetes-admin-context \
--cluster=kubernetes --user=new-kubernetes-admin
```

* 作用:创建一个上下文,关联前面定义的集群和用户。
* 上下文方便切换和使用。

```bash
kubectl config --kubeconfig=new-admin.kubeconfig use-context new-kubernetes-admin-context
```

* 作用:设置当前 kubeconfig 默认使用这个上下文。

---

# 4. 创建 ClusterRoleBinding,授权给 Group

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: new-cluster-admin-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: Group
name: new-system:masters
apiGroup: rbac.authorization.k8s.io
```

* 作用:

* 给 Kubernetes 集群中 `Group` 类型的主体授权,组名是 `new-system:masters`。
* 绑定角色是 `cluster-admin`,这是 Kubernetes 内置超级管理员角色。
* 重要点:这里**不是授权给具体某个用户**,而是授权给所有带 `O=new-system:masters` 的用户。
* 这样,任何使用含有 `O=new-system:masters` 的证书登录的用户,都获得管理员权限。

---

# 5. 验证权限

```bash
KUBECONFIG=new-admin.kubeconfig kubectl get nodes
```

* 作用:

* 使用你新创建的 kubeconfig 文件。
* 如果 RBAC 绑定生效,命令会成功返回节点列表,表明拥有管理员权限。
* 否则会返回权限拒绝错误。

---

# 总结

* **CN 是用户身份标识**,**O 是用户组标识**,这两者都来自客户端证书的 Subject。
* Kubernetes 的 apiserver 会用 CA 验证证书,然后提取 CN 和 O,作为认证身份。
* RBAC 授权时可以绑定用户(User)或组(Group),**对组授权时,只要证书带有对应的组 O,就会拥有绑定的权限**。
* 你的流程是:

* 签发带组的证书 → 用该证书创建 kubeconfig → 创建对该组的 ClusterRoleBinding → 验证权限。

如有需要,我可以帮你做更细粒度的 RBAC 授权示例,或者帮你写自动化脚本。

-----------------------------
以下是完整的 Kubernetes Admission Webhook 实现方案,用于长期拦截 **所有 namespace 中 system\:masters 组(/O=system\:masters)发起的所有资源操作请求**,防止使用该组访问敏感资源。此方案支持部署到生产环境,具有可维护性和可扩展性。

---

## ✅ 功能目标

* 拦截 `userInfo.groups` 包含 `system:masters` 的所有 `CREATE`、`UPDATE`、`DELETE` 等请求;
* 拒绝所有被匹配的请求;
* 可长期运行在生产环境,支持 HTTPS 通信;
* 兼容所有 Kubernetes 版本(>=1.16);
* 支持动态 webhook 更新与热插拔;

---

## 🧱 核心组成

| 模块 | 说明 |
| ------------------------------ | ----------------------------- |
| Admission Webhook 服务 | 用于接收 API 请求并判断用户组 |
| TLS 证书 | 提供给 kube-apiserver 访问 webhook |
| Service + Deployment | 使 webhook pod 在集群中可访问 |
| ValidatingWebhookConfiguration | 定义 webhook 拦截行为(所有命名空间+资源) |
| Secret | 包含 webhook TLS |

---

## 🧰 部署步骤(最小可运行示例)

---

### 🔹 第 1 步:准备 TLS 证书

> 可使用 OpenSSL、cfssl 或 cert-manager 签发,以下为手动方式。

```bash
# 创建 CA
openssl genrsa -out ca.key 2048
openssl req -x509 -new -key ca.key -subj "/CN=Webhook CA" -days 3650 -out ca.crt

# 创建服务端证书
openssl genrsa -out tls.key 2048
openssl req -new -key tls.key -subj "/CN=webhook-service.webhook-ns.svc" -out tls.csr

# 签发服务端证书
openssl x509 -req -in tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out tls.crt -days 365 -extensions v3_req -extfile <(cat <<EOF
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = webhook-service
DNS.2 = webhook-service.webhook-ns
DNS.3 = webhook-service.webhook-ns.svc
EOF
)
```

---

### 🔹 第 2 步:部署 Webhook Server(Python 示例)

#### webhook.py

```python
from flask import Flask, request, jsonify
app = Flask(__name__)

@app.route("/validate", methods=["POST"])
def validate():
body = request.get_json()
uid = body["request"]["uid"]
groups = body["request"]["userInfo"].get("groups", [])
if "system:masters" in groups:
return jsonify({
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {
"uid": uid,
"allowed": False,
"status": {"message": "Access denied: system:masters is not allowed"}
}
})
return jsonify({
"apiVersion": "admission.k8s.io/v1",
"kind": "AdmissionReview",
"response": {"uid": uid, "allowed": True}
})

app.run(host="0.0.0.0", port=443, ssl_context=("/certs/tls.crt", "/certs/tls.key"))
```

#### Dockerfile

```Dockerfile
FROM python:3.9-slim
RUN pip install flask
COPY webhook.py /webhook.py
COPY tls.crt tls.key /certs/
CMD ["python", "/webhook.py"]
```

构建并上传镜像:

```bash
docker build -t your-registry/deny-system-masters:latest .
docker push your-registry/deny-system-masters:latest
```

---

### 🔹 第 3 步:部署到 Kubernetes

```yaml
apiVersion: v1
kind: Namespace
metadata:
name: webhook-ns
---
apiVersion: v1
kind: Secret
metadata:
name: webhook-tls
namespace: webhook-ns
type: kubernetes.io/tls
data:
tls.crt: <base64 of tls.crt>
tls.key: <base64 of tls.key>
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook-server
namespace: webhook-ns
spec:
replicas: 1
selector:
matchLabels:
app: webhook
template:
metadata:
labels:
app: webhook
spec:
containers:
- name: webhook
image: your-registry/deny-system-masters:latest
ports:
- containerPort: 443
volumeMounts:
- name: tls
mountPath: "/certs"
readOnly: true
volumes:
- name: tls
secret:
secretName: webhook-tls
---
apiVersion: v1
kind: Service
metadata:
name: webhook-service
namespace: webhook-ns
spec:
ports:
- port: 443
targetPort: 443
selector:
app: webhook
```

---

### 🔹 第 4 步:创建 ValidatingWebhookConfiguration

```yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: deny-system-masters
webhooks:
- name: deny.system.masters.k8s.io
clientConfig:
service:
name: webhook-service
namespace: webhook-ns
path: /validate
caBundle: <base64 of ca.crt>
rules:
- operations: ["*"]
apiGroups: ["*"]
apiVersions: ["*"]
resources: ["*"]
scope: "*"
failurePolicy: Fail
sideEffects: None
admissionReviewVersions: ["v1"]
```

---

## 🔍 验证与测试

使用带有 `system:masters` 组的证书发起请求应收到拒绝响应:

```bash
kubectl get pods --kubeconfig old-admin.kubeconfig
# Error from server: "Access denied: system:masters is not allowed"
```

---

## 🔒 安全与维护建议

* 可通过 Label、Selector 控制哪些 Namespace 触发 webhook;
* 可升级为 Go + controller-runtime 管理 webhook;
* 使用 cert-manager 自动续期;
* 日志应启用持久化(如挂载 PV)或推送至 ELK/FluentBit;
* 可扩展为双向认证(mTLS)提高安全性。

---

如果你需要 Helm Chart 或使用 Go 重写版本(可读性强,适合长期维护),我可以提供完整代码与 CI/CD 部署方案。

是否现在要我整理 Helm Chart / Kustomize 或生成一套 Go 实现的 Webhook?

 

 

posted on 2025-07-07 17:04  吃草的青蛙  阅读(16)  评论(0)    收藏  举报

导航