Giter Site home page Giter Site logo

wjiec / alidns-webhook Goto Github PK

View Code? Open in Web Editor NEW
32.0 1.0 9.0 160 KB

alidns-webhook is a generic ACME solver for cert-manager.

License: MIT License

Dockerfile 2.26% Makefile 4.89% Go 77.05% Mustache 15.80%
acme acme-dns alidns cert-manager cert-manager-webhook

alidns-webhook's Introduction

Alidns-Webhook

Go Report Card GitHub license

Overview

alidns-webhook is a generic ACME solver for cert-manager.

Quick start

This tutorial will detail how to configure and install the webhook to your cluster with alidns.

Install webhook

Before installing this webhook, make sure you have cert-manager installed correctly. If you haven't installed it yet, you can get the installation instructions from the cert-manager documentation.

If you have Helm, you can deploy the alidns-webhook with the following command:

helm upgrade --install alidns-webhook alidns-webhook \
    --repo https://wjiec.github.io/alidns-webhook \
    --namespace cert-manager --create-namespace \
    --set groupName=acme.yourcompany.com

# Note: If you installed cert-manager via bitnami charts, you need to add the additional
#   `--set certManager.serviceAccountName=cert-manager-controller`
# parameter to specify the ServiceAccount to use.

It will install the alidns-webhook in the cert-manager namespace, creating that namespace if it doesn't already exist.

Configure a issuer

Create this definition locally and update the email address and groupName to your own. Please see more details in cert-manager configuration.

Ensure the groupName matches the config in the webhook.

#
# example-acme-issuer.yaml
#

apiVersion: v1
kind: Secret
metadata:
  name: alidns-secret
  namespace: cert-manager
stringData:
  access-key-id: "Your Access Key Id"
  access-key-secret: "Your Access Key Secret"
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: example-acme
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: [email protected] # Change ME
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: example-acme
    solvers:
      - dns01:
          webhook:
            groupName: acme.yourcompany.com # Change ME
            solverName: alidns
            config:
              region: "cn-hangzhou" # Optional
              accessKeyIdRef:
                name: alidns-secret
                key: access-key-id
              accessKeySecretRef:
                name: alidns-secret
                key: access-key-secret

Once edited, apply the custom resource:

kubectl create --edit -f example-acme-issuer.yaml

Creating Certificate or deploy a TLS Ingress

We can deploy a certificate directly on Ingress, edit the ingress add the annotations:

kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: foo-example-com
  annotations:
    cert-manager.io/cluster-issuer: "example-acme"
    # cert-manager.io/issuer: "example-acme"
spec:
  tls:
  - hosts:
    - foo.example.com
    secretName: foo-example-com-tls
  rules:
  - host: foo.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: backend-service
            port:
              name: http

Or we can create a Certificate resource that is to be honored by an issuer which is to be kept up-to-date.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: star-example-com
spec:
  secretName: star-example-com-tls
  commonName: "example.com"
  dnsNames:
  - "example.com"
  - "*.example.com"
  issuerRef:
    name: example-acme
    kind: ClusterIssuer
    # kind: Issuer

Then we can refer to that secrets(secretName) in Ingress.

Supported Versions table

The following table lists the correspondences between alidns-webhook and k8s versions.

Alidns-Webhook version k8s supported version Helm Chart Version
v1.0.0 1.29, 1.28, 1.27, 1.26 1.0.*
v0.1.0 1.29, 1.28, 1.27, 1.26 0.1.*

License

MIT License

alidns-webhook's People

Contributors

dependabot[bot] avatar wjiec avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

alidns-webhook's Issues

Failed to load alidns cause by "failed reading secret \"cert-manager/\": resource name may not be empty"

`
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-pro
spec:
acme:
# The ACME server URL, 使用staging环境颁发的证书无法正常公网使用,需要本地添加受信任根证书
# server: https://acme-staging-v02.api.letsencrypt.org/directory
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: [email protected]
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-pro-account-key
solvers:
- dns01:
webhook:
groupName: "acme.yourcompany.com"
solverName: alidns
config:
region: ""
accessKeyIdRef:
name: aliyun-api-token-secret
key: access-key
secretKeySecretRef:
name: aliyun-api-token-secret
key: secret-key


apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: m6exyz-cn-ca-tsl
labels:
app: alidns-webhook
spec:
duration: 2160h # 90d
renewBefore: 360h # 15d
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
secretName: ca-tsl
dnsNames:

  • "xxx.cn"
  • "*.xxx.cn"
    issuerRef:
    name: letsencrypt-pro

    We can reference ClusterIssuers by changing the kind here.

    The default value is Issuer (i.e. a locally namespaced Issuer)

    kind: ClusterIssuer
    `

cert-manager1.15 版本报错

安装命令

helm upgrade --install alidns-webhook alidns-webhook     --repo https://wjiec.github.io/alidns-webhook     --namespace cert-manager     --set groupName=acme.xxx.com

创建 issuer

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: dns-aliyun
spec:
  acme:
    # Change to your letsencrypt email
    server: https://acme.zerossl.com/v2/DV90
    externalAccountBinding:
      keyID: ***************
      keySecretRef:
        name: **********
        key: secret
    privateKeySecretRef:
      name: dns-aliyun-account
    solvers:
    - dns01:
        webhook:
          groupName: acme.xxx.com
          solverName: alidns
          config:
            region: ""
            accessKeyIdRef:
              name: aliyun-raw-dns
              key: access-key
            accessKeySecretRef:
              name: aliyun-raw-dns
              key: secret-key

报错信息

alidns.acme.xxx.com is forbidden: User "system:serviceaccount:cert-manager:cert-manager-controller" cannot create resource "alidns" in API group "acme.xxx.com" at the cluster scope

镜像不在白名单中无法拉取

helm后pod提示拉取镜像失败

Failed to pull image "wjiec/alidns-webhook:v1.0.0": failed to pull and unpack image "docker.io/wjiec/alidns-webhook:v1.0.0": failed to copy: httpReadSeeker: failed open: unexpected status code https://docker.m.daocloud.io/v2/wjiec/alidns-webhook/blobs/sha256:9d71258193bd68406e73d5b23da278555d8494c44b55b69286176f521cb0f6e1?ns=docker.io: 403 Forbidden - Server message: denied: 🚫 这镜像不在白名单. this image is not in the allowlist.

kubelet MountVolume.SetUp failed for volume "certs" : secret "alidns-webhook-tls" not found

Name: alidns-webhook-8596b8dfcf-z9s22
Namespace: cert-manager
Priority: 0
Service Account: alidns-webhook
Node: m6e/10.168.1.172
Start Time: Thu, 18 Jan 2024 00:03:50 +0800
Labels: app.kubernetes.io/instance=alidns-webhook
app.kubernetes.io/name=alidns-webhook
pod-template-hash=8596b8dfcf
Annotations:
Status: Pending
IP:
IPs:
Controlled By: ReplicaSet/alidns-webhook-8596b8dfcf
Containers:
alidns-webhook:
Container ID:
Image: wjiec/alidns-webhook:v0.1.0
Image ID:
Port: 443/TCP
Host Port: 0/TCP
Args:
--tls-cert-file=/tls/tls.crt
--tls-private-key-file=/tls/tls.key
State: Waiting
Reason: ContainerCreating
Ready: False
Restart Count: 0
Liveness: http-get https://:https/healthz delay=0s timeout=1s period=10s #success=1 #failure=3
Readiness: http-get https://:https/healthz delay=0s timeout=1s period=10s #success=1 #failure=3
Environment:
GROUP_NAME: acme.yourcompany.com
Mounts:
/tls from certs (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4cgnm (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
certs:
Type: Secret (a volume populated by a Secret)
SecretName: alidns-webhook-tls
Optional: false
kube-api-access-4cgnm:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional:
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors:
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message


Warning FailedMount 25s (x271 over 8h) kubelet MountVolume.SetUp failed for volume "certs" : secret "alidns-webhook-tls" not found

failed reading secret "cert-manager": resource name may not be empty

pod/alidns-webhook-68f86c46c4-jw72j 每 2 分钟报这个 E1230

E1230 14:13:42.301460       1 alidns.go:51] Failed to load alidns cause by "failed reading secret \"cert-manager/\": resource name may not be empty"

目标是在 kube-prometheus-stack namespace 中创建 ingress-nginx。

k8s 版本 v1.27.8

执行代码如下:

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set installCRDs=true

helm install alidns-webhook alidns-webhook/alidns-webhook \
    --namespace cert-manager --create-namespace \
    --set groupName=xxxxxx

在 kube-prometheus-stack、cert-manager 两个namespace 均有创建 secret

apiVersion: v1
kind: Secret
metadata:
  name:  alidns
stringData:
  access-key-id: xxxxxx
  access-key-secret: xxxxxx

ClusterIssuer 如下:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: ali-letsencrypt-staging
spec:
  acme:
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: xxxxxx
    privateKeySecretRef:
      name: ali-letsencrypt-staging
    solvers:
    - dns01:
        webhook:
          groupName: xxxxxx
          solverName: alidns
          config:
            region: "cn-beijing"
            accessKeySecretRef:
              name: alidns
              key: access-key-id
            secretKeySecretRef:
              name: alidns
              key: access-key-secret

在 kube-prometheus-stack namespace 创建 ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ali-grafana
  annotations:
    cert-manager.io/cluster-issuer: ali-letsencrypt-staging
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - xxxxxx
    secretName: grafana-ali-letsencrypt-staging
  rules:
  - host: xxxxxx
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: grafana-service
            port:
              number: 80

在创建 ingress 的同时,会自动创建名字为 grafana-ali-letsencrypt-staging 的 Certificate。
Certificate 的 SECRET 是 grafana-ali-letsencrypt-staging。
但 READY 状态是 False。
kube-prometheus-stack namespace 下也自动创建了名字为 grafana-ali-letsencrypt-staging-2ddsj 的 secret。

不知道为何 pod 要读 cert-manager 这个 secret,这个 secret 名字是如何传进去的。
我曾把 Secret 的名字由 alidns 改为了 cert-manager,但还是会报相同的错误。

Observed a panic: runtime error: invalid memory address or nil pointer dereference

When I apply for certificate resource making hapeened QAQ~~
Something like show this:
goroutine 1065 [running]:
k8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest.func1.1()
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/finisher/finisher.go:105 +0xa5
panic({0x22c3de0, 0x3def120})
/usr/local/go/src/runtime/panic.go:884 +0x213
github.com/alibabacloud-go/darabonba-openapi/v2/client.(*Client).DoRequest.func1(0xc0006fb800, 0xc0006f6780, 0xc0006a8d40, 0xc000012ec8, 0xc000b1d6b8?)
/go/pkg/mod/github.com/alibabacloud-go/darabonba-openapi/[email protected]/client/client.go:1355 +0xf1e
github.com/alibabacloud-go/darabonba-openapi/v2/client.(*Client).DoRequest(0xc0006fb800, 0x0?, 0xc0006c49c0?, 0xc0006b3dd0)
/go/pkg/mod/github.com/alibabacloud-go/darabonba-openapi/[email protected]/client/client.go:1500 +0xc88
github.com/alibabacloud-go/darabonba-openapi/v2/client.(*Client).CallApi(0xc0006fb800, 0xc0006f6780, 0x26864ed?, 0xb?)
/go/pkg/mod/github.com/alibabacloud-go/darabonba-openapi/[email protected]/client/client.go:1685 +0x498
github.com/alibabacloud-go/alidns-20150109/v4/client.(*Client).DescribeDomainRecordsWithOptions(0xc0006fb800, 0xc0000ea700, 0xc000b1d9e8?)
/go/pkg/mod/github.com/alibabacloud-go/alidns-20150109/[email protected]/client/client.go:29580 +0xae5
github.com/alibabacloud-go/alidns-20150109/v4/client.(*Client).DescribeDomainRecords(0x1?, 0xc000b1daa0?)
/go/pkg/mod/github.com/alibabacloud-go/alidns-20150109/[email protected]/client/client.go:29599 +0x54
main.(*AliDNS).AddRecord(0xc000012e60, {0xc0003f1470, 0x25}, {0xc0007cf100, 0xd}, {0xc0003f1440, 0x2b})
/workspace/alidns.go:184 +0x21e
main.(*AliSolver).Present(0x2568c20?, 0xc00089d200)
/workspace/alidns.go:57 +0x1e6
github.com/cert-manager/cert-manager/pkg/acme/webhook/registry/challengepayload.(*REST).callSolver(0xc00055cc70, {{0x0, 0x0}, {0xc0007cf0e0, 0x7}, {0xc0007cf0e8, 0x6}, {0xc000772dc8, 0x14}, {0xc0003f1440, ..
.}, ...})
/go/pkg/mod/github.com/cert-manager/[email protected]/pkg/acme/webhook/registry/challengepayload/challenge_payload.go:90 +0x168
github.com/cert-manager/cert-manager/pkg/acme/webhook/registry/challengepayload.(*REST).Create(0x0?, {0x6c3001?, 0xc0007a2810?}, {0x2a23d70?, 0xc0007a2810}, 0x2a44160?, 0x2a557a0?)
/go/pkg/mod/github.com/cert-manager/[email protected]/pkg/acme/webhook/registry/challengepayload/challenge_payload.go:70 +0xe5
k8s.io/apiserver/pkg/endpoints/handlers.(*namedCreaterAdapter).Create(0x0?, {0x2a41008?, 0xc0007a2db0?}, {0xc0006a3e60?, 0x2a44160?}, {0x2a23d70?, 0xc0007a2810?}, 0xc00079d5e0?, 0xf?)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/create.go:254 +0x42
k8s.io/apiserver/pkg/endpoints/handlers.createHandler.func1.1()
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/create.go:183 +0xd8
k8s.io/apiserver/pkg/endpoints/handlers.createHandler.func1.2()
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/create.go:209 +0x413
k8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest.func1()
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/finisher/finisher.go:117 +0x8f
created by k8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/finisher/finisher.go:92 +0xde
goroutine 1080 [running]:
k8s.io/apiserver/pkg/server/filters.(*timeoutHandler).ServeHTTP.func1.1()
/go/pkg/mod/k8s.io/[email protected]/pkg/server/filters/timeout.go:110 +0x9c
panic({0x21aa620, 0xc00091fb60})
/usr/local/go/src/runtime/panic.go:884 +0x213
k8s.io/apiserver/pkg/endpoints/handlers/finisher.(*result).Return(0xc0007af770?)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/finisher/finisher.go:53 +0xbc
k8s.io/apiserver/pkg/endpoints/handlers/finisher.finishRequest({0x2a41008, 0xc0007a2db0}, 0xc0007a0360, 0x45d964b800, 0x27bd208)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/finisher/finisher.go:126 +0x376
k8s.io/apiserver/pkg/endpoints/handlers/finisher.FinishRequest(...)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/finisher/finisher.go:84
k8s.io/apiserver/pkg/endpoints/handlers.createHandler.func1({0x2a402c0, 0xc0008be200}, 0xc0006fac00)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/handlers/create.go:193 +0x217a
k8s.io/apiserver/pkg/endpoints.restfulCreateResource.func1(0xc0008be1e0, 0xc000108000)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/installer.go:1276 +0xcb
k8s.io/apiserver/pkg/endpoints/metrics.InstrumentRouteFunc.func1(0xc0008be1e0, 0xc000108000)
/go/pkg/mod/k8s.io/[email protected]/pkg/endpoints/metrics/metrics.go:571 +0x22c
github.com/emicklei/go-restful/v3.(*Container).dispatch(0xc000774000, {0x2a402c0, 0xc0008254e0}, 0xc0006fac00)
/go/pkg/mod/github.com/emicklei/go-restful/[email protected]/container.go:299 +0x5db
github.com/emicklei/go-restful/v3.(*Container).Dispatch(...)
/go/pkg/mod/github.com/emicklei/go-restful/[email protected]/container.go:204
k8s.io/apiserver/pkg/server.director.ServeHTTP({{0x268f9c7?, 0x40bd94?}, 0xc000774000?, 0xc00065e690?}, {0x2a402c0, 0xc0008254e0}, 0xc0006fac00)
/go/pkg/mod/k8s.io/[email protected]/pkg/server/handler.go:146 +0x4e7

So....How to fix this problem

Certificate resource code like this:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: cert-test-ssl
namespace: website
spec:
secretName: cert-test-ssl-tls
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
dnsNames:

  • certssl.tomharry.com

Kubernetes Version: 1.28+

Issuing certificate as Secret does not exist

Status:
  Conditions:
    Last Transition Time:        2024-06-19T03:57:50Z
    Message:                     Issuing certificate as Secret does not exist
    Observed Generation:         1
    Reason:                      DoesNotExist
    Status:                      False
    Type:                        Ready
    Last Transition Time:        2024-06-19T03:57:50Z
    Message:                     Issuing certificate as Secret does not exist
    Observed Generation:         1
    Reason:                      DoesNotExist
    Status:                      True
    Type:                        Issuing
  Next Private Key Secret Name:  stat-xioobu-cn.tls-5s8qm
Events:                          <none>
root@lax:~/.laf/mydeploy# kubectl get certificate
NAME                 READY   SECRET               AGE
stat-xioobu-cn.tls   False   stat-xioobu-cn.tls   118m
root@lax:~/.laf/mydeploy# kubectl get secret
NAME                       TYPE     DATA   AGE
stat-xioobu-cn.tls-5s8qm   Opaque   1      118m
apiVersion: v1
kind: Secret
metadata:
  name: alidns-secret
  namespace: cert-manager
stringData:
  access-key-id: ""
  access-key-secret: ""
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: xioobu-acme
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: [email protected] # Change ME
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: xioobu-acme
    solvers:
      - dns01:
          webhook:
            groupName: acme.xioobu.cn # Change ME
            solverName: alidns
            config:
              accessKeyIdRef:
                name: alidns-secret
                key: access-key-id
              accessKeySecretRef:
                name: alidns-secret
                key: access-key-secret
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: stat-xxx-cn
  annotations:
    cert-manager.io/cluster-issuer: "xxx-acme"
    # cert-manager.io/issuer: "example-acme"
spec:
  tls:
  - hosts:
    - laf.xxx.cn
    secretName: stat-xxx-cn.tls
  rules:
  - host: laf.xxx.cn
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: backend-service
            port:
              name: http

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.