我已从 Azure 应用服务证书购买了通配符 ssl 证书。我还有一个 AKS 集群。我想把它放在秘密中并在入口中使用。购买后,它将秘密文件存储在 Azure Key Vault 中。我下载了它,然后导入以创建 Azure Key Vault 证书。然后,我使用 akv2k8s 在 AKS 中创建了一个秘密文件,并在 ingress 中使用它。在我的应用程序抛出“err_cert_authority_invalid”错误之后。 我做错了什么吗? 关于 ssl 和 ingress 的文档并不多。在许多文章中,他们使用“让加密”或“证书管理器”。
• 这可能是由于误解证书是由临时环境颁发的,反之亦然。因此,为此目的,我建议您检查 ‘stable/wordpress’ helm 图表,其中包含入口注释 'certmanager.k8s.io/cluster-issuer': 'letsencrypt-staging'。这将导致伪造的颁发者颁发证书。因此,即使您的证书作为机密进入 AKS,它也会显示为由虚假颁发者颁发,因为证书哈希验证链在中间被破坏。请在下面找到用于此目的的卷曲:-
‘ # curl -vkI https://blog.my-domain.com/
...
* Server certificate:
* subject: CN=blog.my-domain.com
* start date: May 13 08:51:13 2019 GMT
* expire date: Aug 11 08:51:13 2019 GMT
* issuer: CN=Fake LE Intermediate X1
... ‘
然后,列出入口如下:-
‘ # kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
blog-wordpress blog.my-domain.com 35.200.214.186 80, 443 8m48s ’
还有证书:-
‘ # kubectl get certificates
NAME READY SECRET AGE
wordpress.local-tls True wordpress.local-tls 9m ’
然后,将证书的颁发者切换为最初颁发证书的颁发者,如下所示:-
‘ # kubectl edit ing blog-wordpress ’
并更新注释如下:-
‘ certmanager.k8s.io/cluster-issuer: letsencrypt-prod ’
一旦更新入口清单,证书清单将自动更新。要验证它,请打开 ‘wordpress.local-tls’ 证书资源的清单,如下所示:-
‘ kubectl edit certificate wordpress.local-tls ’
发行人将被视为更新如下:-
‘ kubectl edit certificate wordpress.local-tls ’
因此,通过这种方式,您将能够在 AKS 中导入证书机密。如需了解更多详情,我建议您参考以下链接了解更多详情:-
https://github.com/vmware-archive/kube-prod-runtime/issues/532
我在通配符证书方面遇到了同样的问题,我考虑了不同的方法:
null_resource
的 terraform,它将等待配置证书我对解决方案 1 和 2 不满意,因为就我而言,我不知道证书何时会在 Azure 端准备就绪。
因此,为了使其与 Nginx 同时部署,我结合使用了 SecretProviderClass 和 Helm 预同步挂钩。
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: az-kv-domain-certificate
spec:
provider: azure
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "false"
clientID: {{ .Values.azureKVCSI.clientId }}
keyvaultName: {{ .Values.azureKVCSI.keyVaultName }} # Set to the name of your key vault
objects: |
array:
- |
objectName: {{ .Values.azureKVCSI.secretName }}
objectType: secret # object types: secret, key, or cert
objectVersion: "" # [OPTIONAL] object versions, default to latest if empty
tenantId: {{ .Values.azureKVCSI.tenantId }}
secretObjects:
- secretName: {{ .Release.Name }}-ingress-nginx-domain-certificate
type: Opaque
data:
- objectName: wildcard-cert
key: cert.pkcs12
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-5"
name: ingress-nginx-wildcard-reload-role
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- list
- watch
- create
- update
- patch
- delete
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ingress-nginx-wildcard-reload-rolebinding
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-5"
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: ingress-nginx-wildcard-reload-role
subjects:
- kind: ServiceAccount
name: ingress-nginx
namespace: {{ .Release.Namespace }}
---
apiVersion: v1
kind: Secret
metadata:
name: ingress-nginx-wildcard-reload-token
annotations:
kubernetes.io/service-account.name: ingress-nginx
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
"helm.sh/hook-weight": "-5"
type: kubernetes.io/service-account-token
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "ingress-nginx.fullname" . }}-wildcard-reload
namespace: {{ .Release.Namespace }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
labels:
{{- include "ingress-nginx.labels" . | nindent 4 }}
app.kubernetes.io/component: admission-webhook
azure.workload.identity/use: "true"
spec:
{{- if .Capabilities.APIVersions.Has "batch/v1alpha1" }}
# Alpha feature since k8s 1.12
ttlSecondsAfterFinished: 0
{{- end }}
template:
metadata:
name: {{ include "ingress-nginx.fullname" . }}-wildcard-reload
labels:
{{- include "ingress-nginx.labels" . | nindent 8 }}
app.kubernetes.io/component: admission-webhook
spec:
containers:
- name: create
image: todo # put here an image containing kubectl and openssl
command:
- "/bin/bash"
- "-c"
args:
- |
#!/bin/bash
set -e
IN_FILE="/mnt/azure-kv-cert-csi/wildcard-pprd"
mkdir /tmp/certs
cp "${IN_FILE}" /tmp/certs
cd /tmp/certs
base64 -d "${IN_FILE}" > "/tmp/certs/wildcard-pprd_base64_decoded"
IN_FILE="/tmp/certs/wildcard-pprd_decoded"
echo "Converting the certificate from PFX to KEY and CRT..."
echo "" > pfx_pass
echo "0000" > pfx_pass_in_out
IMPORT_PASSWORD="file:pfx_pass"
PASSPH="file:pfx_pass_in_out"
openssl pkcs12 -in "${IN_FILE}" -nocerts -out "${IN_FILE}_encrypted.key" -password $IMPORT_PASSWORD -passin $PASSPH -passout $PASSPH && \
openssl rsa -in "${IN_FILE}_encrypted.key" -passin $PASSPH | sed -ne '/-BEGIN PRIVATE KEY-/,/-END PRIVATE KEY-/p' > "${IN_FILE}.key" && echo "OK: Converted to KEY"
openssl pkcs12 -in "${IN_FILE}" -clcerts -nokeys -password $IMPORT_PASSWORD -passin $PASSPH -passout $PASSPH | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > "${IN_FILE}.crt" && echo "OK: Converted to CRT"
# configure kubectl
kubectl config set-cluster local --server=https://kubernetes.default --certificate-authority=/kube-api-ca/ca.crt
kubectl config set-credentials ingress-nginx --token="${KUBE_SA_TOKEN}" --certificate-authority=/kube-api-ca/ca.crt
kubectl config set-context local --cluster=local --user=ingress-nginx --namespace=nginx-ingress-controller
echo "Creating the kubernetes secret..."
kubectl create secret tls default-tls-test --key="${IN_FILE}.key" --cert="${IN_FILE}.crt"
echo "Done, exiting..."
env:
- name: KUBE_SA_TOKEN
valueFrom:
secretKeyRef:
name: ingress-nginx-wildcard-reload-token
key: token
volumeMounts:
- mountPath: /mnt/azure-kv-cert-csi
name: azure-kv-cert-csi
readOnly: true
- mountPath: "/kube-api-ca"
name: kube-ca
readOnly: true
restartPolicy: OnFailure
serviceAccountName: ingress-nginx
volumes:
- name: kube-ca
secret:
secretName: ingress-nginx-wildcard-reload-token
items:
- key: ca.crt
path: ca.crt
- csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: az-kv-domain-certificate
name: azure-kv-cert-csi
extraArgs:
default-ssl-certificate: 'nginx-ingress-controller/default-tls'
作为补充,我建议也将其添加为 cronjob,这样您就可以确保该作业每隔一段时间运行一次,并且在证书到期时不会感到意外。