【问题标题】:Wildcard SSL certificate with subdomain redirect in KubernetesKubernetes 中带有子域重定向的通配符 SSL 证书
【发布时间】:2019-01-07 21:03:22
【问题描述】:

我已经使用 cert-manager 和letsencrypt 将我的Kubernetes 配置为对我的所有应用程序使用一个通配符SSL 证书,现在的问题是我无法配置子域重定向,因为Ingress 有点“僵硬”。以下是我试图实现这一目标的方法:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-wildcard-ingress
  namespace: mynamespace
  annotations:
    kubernetes.io/ingress.class: nginx
    certmanager.k8s.io/cluster-issuer: letsencrypt-prod
    certmanager.k8s.io/acme-challenge-type: dns01
    certmanager.k8s.io/acme-dns01-provider: azuredns
    ingress.kubernetes.io/force-ssl-redirect: "true"
    ingress.kubernetes.io/ssl-redirect: "true"
spec:
  rules:
  - host: "domain.com"
    http:
      paths:
      - path: /
        backend:
          serviceName: some-service
          servicePort: 3000          
  - host: somesub.domain.com
    http:
      paths:
      - path: /
        backend:
          serviceName: some-other-service
          servicePort: 80
  - host: othersub.domain.com
    http:
      paths:
      - path: /
        backend:
          serviceName: one-more-service
          servicePort: 8080          
  - host: "*.domain.com"
    http:
      paths:
      - path: /
        backend:
          serviceName: default-service-to-all-other-non-mapped-subdomains
          servicePort: 8000          

  tls:
  - secretName: domain-com-tls
    hosts:         
     - "*.domain.com.br"

问题在于 Ingress 忽略了声明的子域重定向,因为它们没有在“tls:hosts”部分中列出。如果我确实将它们放在那里,它会尝试使用通配符和其他子域以及同一证书中的其他子域颁发 SSL 证书,这会导致颁发者拒绝订单,说的很明显:“subdomain.domain.com 和 * .domain.com 是多余的”

还有其他方法可以声明这些重定向并强制它们使用我的 SSL 通配符证书吗?

【问题讨论】:

    标签: kubernetes lets-encrypt wildcard-subdomain kubernetes-ingress cert-manager


    【解决方案1】:

    好吧,对于任何遇到这种麻烦的人,我已经设法解决了它(不是最好的解决方案,但这是一个开始)。为此,我将使用 cert-manager 和letsencrypt。

    首先,我创建了一个 ClusterIssuer 来使用letsencrypt为我的证书颁发:

    apiVersion: certmanager.k8s.io/v1alpha1
    kind: ClusterIssuer
    metadata:      
      name: letsencrypt-prod-dns
    spec:
      acme:
        dns01:
          providers:
          - azuredns:
              clientID: MY_AZURE_CLIENT_ID
              clientSecretSecretRef:
                key: client-secret
                name: azure-secret
              hostedZoneName: mydomain.com
              resourceGroupName: MY_AZURE_RESOURCE_GROUP_NAME
              subscriptionID: MY_AZURE_SUBSCRIPTION_ID
              tenantID: MY_AZURE_TENANT_ID
            name: azuredns
        email: somemail@mydomain.com
        privateKeySecretRef:
          key: ""
          name: letsencrypt-prod-dns
        server: https://acme-v02.api.letsencrypt.org/directory
    

    然后我为我的所有子域创建了一个后备入口(这将是证书生成器):

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        certmanager.k8s.io/acme-challenge-type: dns01
        certmanager.k8s.io/acme-dns01-provider: azuredns
        certmanager.k8s.io/cluster-issuer: letsencrypt-prod-dns
        ingress.kubernetes.io/force-ssl-redirect: "true"
        ingress.kubernetes.io/ssl-redirect: "true"    
        kubernetes.io/ingress.class: nginx    
      name: wildcard-ingress
      namespace: some-namespace  
    spec:
      rules:
      - host: '*.mydomain.com'
        http:
          paths:
          - backend:
              serviceName: some-default-service
              servicePort: 80
            path: /      
      tls:
      - hosts:
        - '*.mydomain.com'
        - mydomain.com
        secretName: wildcard-mydomain-com-tls
    

    请注意,我已在 TLS 部分声明了通配符和绝对路径,因此证书对于没有子域的 URL 也有效。

    此时,对您的域的任何请求都将通过 SSL 重定向到“some-default-service”(证书管理器将在您创建后备入口后立即发布新证书。这可能需要一段时间一旦 cert-manager dns01 issuer 还不成熟),太好了!!!

    但是,如果您需要将某个特定子域重定向到另一个服务怎么办?没问题(因为它们在同一个命名空间上运行),您所要做的就是为您的子域创建一个新入口,将其指向您现有的 wildcard-mydomain-com-tls 证书密钥:

    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      annotations:
        ingress.kubernetes.io/force-ssl-redirect: "false"
        ingress.kubernetes.io/ssl-redirect: "true"
        kubernetes.io/ingress.class: nginx
      name: somesubdomain-ingress
      namespace: some-namespace
    spec:
      rules:
      - host: somesubdomain.mydomain.com
        http:
          paths:
          - backend:
              serviceName: some-other-service
              servicePort: 8080
            path: /        
      tls:
      - hosts:
        - somesubdomain.mydomain.com
        secretName: wildcard-mydomain-com-tls
    

    简单的peasy柠檬榨汁!!!现在您的 somesubdomain.mydomain.com 会覆盖您的后备规则并将用户发送到另一个应用程序。您应该注意的唯一一点是,该密钥仅对“some-namespace”命名空间有效,如果您需要在另一个命名空间中使用此证书,您可以:

    1. 将密钥从命名空间“some-namespace”复制到“other-namespace”。如果您这样做,请记住 cert-manager 不会为“其他命名空间”自动更新此证书,因此,每次您的证书过期时,您都必须再次复制该密钥。
    2. 为您拥有的每个命名空间重新创建后备入口,以便为每个命名空间创建一个新证书。这种方法更加冗长,但它是全自动的。

    我想就是这样。希望那里的人可以从这些信息中受益。

    干杯

    【讨论】:

    • 我想早点找到这个。我发现完全一样,但两年后。我想出了相同的想法,但略有不同。我正在使用 ingress-nginx-controller 部署的标志 default-server-tls-secret=$(POD_NAMESPACE)/wildcard-certwildcard-tls-secret=$(POD_NAMESPACE)/wildcard-cert 并将它们设置为我的通配符证书。所以你不需要将你的秘密复制到不同的命名空间中。
    【解决方案2】:

    因此,这里最好的做法可能是不使用 ingress-shim 来管理您的证书资源。

    相反,您可以手动创建证书资源,然后引用它在所有入口中生成的秘密。

    我们目前正在探索解决这个入口限制的选项,但是到目前为止还没有任何进展!

    【讨论】:

    • 好的,我怎样才能做到这一点?我不知道如何创建仅使用现有证书机密的 Ingress。 (sry beeing 这样一个菜鸟,我正在学习,我正在学习......)
    猜你喜欢
    • 2015-04-01
    • 2013-05-20
    • 1970-01-01
    • 2019-01-17
    • 2014-02-28
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多