k8s

externalip-webhook部署

介绍

漏洞

k8s有一个漏洞:https://www.cvedetails.com/cve/CVE-2020-8554/

如果攻击者可以创建或编辑服务和容器,则此漏洞使攻击者能够拦截来自群集中其他容器(或节点)的流量。攻击者可利用该漏洞通过 Kubernetes 上的 LoadBalancer 或 ExternalIP 充当中间人,以便在会话中读取或写入数据。使用externalip-webhook可以进行修复。

漏洞演示请参考:https://my.oschina.net/cncf/blog/4824872(侵删

简介

externalip-webhook 是一个验证 webhook,它可以防止服务使用随机外部 IP。集群管理员可以通过指定 allowed-external-ip-cidrs 参数来指定允许用作外部 IP 的 CIDR 列表。 Webhook 将只允许创建不需要外部 IP 或外部 IP 在管理员指定范围内的服务。 externalip-webhook 还可以通过指定 allowed-usernames 和 allowed-groups 参数来限制谁可以为服务指定允许的外部 IP 范围。

部署

官方地址:https://github.com/kubernetes-sigs/externalip-webhook

  • 要将外部 IP 限制为某些 CIDR,请取消注释并更新 webhook.yaml 中的 allowed-external-ip-cidrs 。
  • 要限制可以为服务指定外部 IP 的用户,请取消注释并更新 webhook.yaml 中的 allowed-usernames 和/或 allowed-groups 。这两个参数的默认值都是空的,这意味着任何用户都可以指定。如果设置了任一参数,则指定外部 IP 仅限于与这些参数中的任何一个匹配的用户。
  • 要限制可以为服务指定外部 IP 的用户,请取消注释并更新 webhook.yaml 中的 allowed-usernames 和/或 allowed-groups 。这两个参数的默认值都是空的,这意味着任何用户都可以指定。如果设置了任一参数,则指定外部 IP 仅限于与这些参数中的任何一个匹配的用户。

file

部署流程

# 我的虚拟机访问不了github
# git clone https://github.com/kubernetes-sigs/externalip-webhook.git
wget https://github.com/kubernetes-sigs/externalip-webhook/archive/refs/heads/master.zip
unzip externalip-webhook-master.zip
make docker-build docker-push IMG=externalip-webhook:v1
make deploy IMG=externalip-webhook:v1

安装kustomize

github中的kustomize地址已经失效了,新的地址是:https://kubectl.docs.kubernetes.io/installation/kustomize/binaries/

# curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"  | bash
wget https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.2.0/kustomize_v4.2.0_linux_amd64.tar.gz
tar xvf kustomize_v4.2.0_linux_amd64.tar.gz
cp kustomize /usr/bin

我的k8s版本是1.22.17,所以这里下载4.2.0的kustomize。
file

file

安装controller-gen

报错:which: no controller-gen in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)

export GOPROXY=https://goproxy.cn/
# git clone https://github.com/kubernetes-sigs/controller-tools.git
wget https://github.com/kubernetes-sigs/controller-tools/archive/refs/heads/master.zip
unzip controller-tools-master.zip
cd controller-tools-master/
go install ./cmd/{controller-gen,helpgen,type-scaffold}
cd $GOPATH
cp controller-gen /usr/bin

file

再次部署报错:go: github.com/ghodss/yaml@v1.0.0: Get https://proxy.golang.org/github.com/ghodss/yaml/@v/v1.0.0.mod: dial tcp 142.251.43.17:443: i/o timeout

file

查看并修改Dockerfile,添加goproxy

ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct

file

报错:denied: requested access to the resource is denied,make命令去掉docker-push即可。即 make docker-build IMG=externalip-webhook:v1

file

查看镜像

file

再次部署

kustomize build config/default | kubectl  delete -f -
make deploy IMG=externalip-webhook:v1

报错:MountVolume.SetUp failed for volume "cert" : secret "webhook-server-cert" not found

file

部署cert-manager

helm repo add bitnami https://charts.bitnami.com/bitnami
helm search repo cert-manager
# kustomize build config/default | kubectl  delete -f -
helm install cert-manager bitnami/cert-manager -n cert-manager --create-namespace --set installCRDs=true
# kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.crds.yaml

最好先把cert-manager安装好,否则就会报下面这个错误,调用validate-externalip.webhook失败。

file

file

查看README中关于webhook-server-cert的描述,需要手动上传证书相关信息。

file

创建自签名证书

openssl genrsa -out ca.key 2048
openssl req -new -key ca.key -x509 -out ca.crt -subj "/CN=my-ca"
openssl genrsa -out tls.key 2048
openssl req -new -key tls.key -out tls.csr -subj "/CN=my-ca"
openssl x509 -req -in tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt
kubectl create secret generic webhook-server-cert --from-file=tls.crt --from-file=tls.key --from-file=ca.crt -n externalip-validation-system

修改manifest.yaml

openssl x509 -in ca.crt -out ca.pem -outform PEM
cat ca.pem

将ca.pem粘贴到 https://base64.supfree.net/ ,进行base64加密,再将加密后的内容粘贴到manifest.yaml。(有坑,见下方的测试)

重新部署

make deploy IMG=externalip-webhook:v1
k get po -n externalip-validation-system
k delete po externalip-validation-webhook-9d48754f9-kr4ks -n externalip-validation-system
k get po -n externalip-validation-system

测试

报错1

创建nginx服务。报错:failed calling webhook "validate-externalip.webhook.svc": unable to load root certificates: unable to parse bytes as PEM block

file

原因是caBundle中pem证书格式有问题,不能被k8s识别。可以用下面的命令来将一个pem证书转换为 k8s可以接受的格式。

cat ca.pem | base64 -w 0

报错2

再次部署,报错:Internal error occurred: failed calling webhook "validate-externalip.webhook.svc": Post "https://externalip-validation-webhook-service.externalip-validation-system.svc:443/validate-service?timeout=10s": x509: certificate is not valid for any names, but wanted to match externalip-validation-webhook-service.externalip-validation-system.svc

file

证书有问题,重新创建。而且不能用上面的 externalip-validation-webhook-service.externalip-validation-system.svc 来当作CN,会报错长度过长。

file

注释namePrefix

vim config/default/kustomization.yaml

file

使用 webhook-service.externalip-validation-system.svc当作CN。

openssl req -new -key ca.key -x509 -out ca.crt -subj "/CN=webhook-service.externalip-validation-system.svc"

报错3

再次替换caBundle,重新部署。报错:Error from server (InternalError): error when creating "nginx.yaml": Internal error occurred: failed calling webhook "validate.webhook.svc": Post "https://webhook-service.externalip-validation-system.svc:443/validate-service?timeout=10s": x509: certificate relies on legacy Common Name field, use SANs or temporarily enable Common Name matching with GODEBUG=x509ignoreCN=0

file

file

这个是因为go在1.15版本之后废弃了CN,推荐使用SAN证书,参考:https://golang.org/doc/go1.15#commonname 。如果你的自签名证书中不包含SANs,就会出现这个报错。

解决方法:重新生成SAN证书

find / -name openssl.cnf
cp /etc/pki/tls/openssl.cnf /etc/ssl/openssl.cnf
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=webhook-service.externalip-validation-system.svc"
openssl genrsa -out tls.key 2048
openssl req -new -key tls.key -out tls.csr -subj "/CN=webhook-service.externalip-validation-system.svc" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:webhook-service.externalip-validation-system.svc,DNS:*.svc"))
openssl x509 -req -days 365  -in tls.csr -out tls.crt -CA ca.crt -CAkey ca.key -CAcreateserial -extensions SAN -extfile <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:webhook-service.externalip-validation-system.svc,DNS:*.svc"))
openssl x509 -noout -text -in tls.crt
openssl x509 -in ca.crt -out ca.pem -outform PEM
cat ca.pem | base64 -w 0
k delete secrets -n externalip-validation-system webhook-server-cert
k create secret generic webhook-server-cert --from-file=tls.crt --from-file=tls.key --from-file=ca.crt -n externalip-validation-system
k delete po -n externalip-validation-system webhook-9d48754f9-9qvpr
k logs -f -n externalip-validation-system webhook-9d48754f9-xfvff
k apply -f /root/nginx.yaml

file

创建成功。

file

file

注:添加环境变量无效

GODEBUG=x509ignoreCN=0
# 在本地,Dockerfile,docker.service中添加都无效,而且Dockerfile中使用的镜像是go1.13.
分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x