近期在给公司内部安装KubeSphere新环境和维护原有KubeSphere环境的过程中,频繁遇到x509: certificate relies on legacy Common Name field, use SANs instead,此问题会影响正常功能的使用,简要介绍其解决方案。

问题描述

本操作过程基于KubeSphere离线安装一文来操作的。

  1. 执行下述命令生成自己的证书

    1
    2
    3
    
    mkdir -p certs
    
    openssl req -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 36500 -out certs/domain.crt
    
  2. 在生成证书的过程中按照文档要求将Common Name的值设置为dockerhub.kubekey.local

    生成自定义证书

  3. /etc/hosts中将dockerhub.kubekey.local映射到当前服务器IP地址

    1
    
    192.168.0.2 dockerhub.kubekey.local
    
  4. Docker信任刚生成的证书

    1
    2
    
    mkdir -p  /etc/docker/certs.d/dockerhub.kubekey.local
    cp certs/domain.crt  /etc/docker/certs.d/dockerhub.kubekey.local/ca.crt
    
  5. 执行下述命令启动Docker仓库

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    docker run -d \
      --restart=always \
      --name registry \
      -v "$(pwd)"/certs:/certs \
      -v /mnt/registry:/var/lib/registry \
      -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
      -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
      -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
      -p 443:443 \
      registry:2
    
  6. 在终端执行docker pull dockerhub.kubekey.local/nginx,运行结果如下,提示原证书的配置方式过期,不能正常使用,问题出现!

    由于证书问题导致本地仓库无法工作

分析与解决

  1. https://go.dev/doc/go1.15#commonname中找到如下一段说明

    The deprecated, legacy behavior of treating the CommonName field on X.509 certificates as a host name when no Subject Alternative Names are present is now disabled by default. It can be temporarily re-enabled by adding the value x509ignoreCN=0 to the GODEBUG environment variable.

    Note that if the CommonName is an invalid host name, it’s always ignored, regardless of GODEBUG settings. Invalid names include those with any characters other than letters, digits, hyphens and underscores, and those with empty labels or trailing dots

    从中可知在Go10.15之后Common Name这个字段已经废弃,可在GODEBUG中通过配置x509ignoreCN=0来重新启用此字段,不过我们是基于GoDocker应用环境,而非Go开发环境,显然此种方式不大可行。

  2. 继续搜索,找到这篇文章how-do-i-use-sans-with-openssl-instead-of-common-name,其中提供了一个解决思路

    Stackoverflow解决方案

  3. 对原有生成证书的步骤改进如下,然后重新执行生成证书

    1
    
    openssl req  -addext "subjectAltName = DNS:dockerhub.kubekey.local" -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key -x509 -days 36500 -out certs/domain.crt
    
  4. 重新执行docker pull dockerhub.kubekey.local/nginx可发现证书问题已经解决

    证书问题解决

  5. 前述执行结果任然报错的原因为镜像不存在,切换为一个已经存在的镜像重新执行即可

    docker可正常拉取镜像