在Docker中生成自签名证书

22

当docker启动时,我需要生成一个自签名证书。基本上我们的docker是使用concourse ci启动的。因此必须在dockerfile中进行,不能使用docker run选项。

请让我知道任何相关的输入。

3个回答

35

简单的RUN命令有什么问题?它对我有效,并成功创建了自签名证书。

FROM debian:wheezy

RUN apt-get update && \
    apt-get install -y openssl && \
    openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 && \
    openssl rsa -passin pass:x -in server.pass.key -out server.key && \
    rm server.pass.key && \
    openssl req -new -key server.key -out server.csr \
        -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com" && \
    openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Dockerfile 中,证书仅在镜像构建期间创建一次;然后您可以在镜像中使用该证书。

如果您需要每次容器启动时都使用新的自签名证书,则可以使用外部 shell 脚本来实现。如下所示:

#!/bin/bash

openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
openssl rsa -passin pass:x -in server.pass.key -out server.key
rm server.pass.key
openssl req -new -key server.key -out server.csr \
    -subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

将该shell脚本放入您的Dockerfile中并设置默认执行:

FROM debian:wheezy

RUN apt-get update && \
    apt-get install -y openssl

COPY generate-certificate.sh /tmp/generate-certificate.sh

CMD [ "/tmp/generate-certificate.sh" ]

每次您使用 docker run .... 启动容器时,都会生成一个新的唯一证书。


1
-passout pass:x 太短 https://bugzilla.redhat.com/show_bug.cgi?id=1467669 - johndpope
你如何为Let's Encrypt证书执行此操作?同时在Dockerfile的RUN命令中生成它们? - perepm
@ppicom 在构建期间启动nginx并运行certbot。但是在构建期间生成letsencrypt证书是没有意义的。它们只有90天左右的有效期,您必须不断重建镜像。将nginx容器与应用程序分开运行更有意义。 - Kevin Kopf
是的,你说得对。我还在努力弄清楚如何为运行在Swarm上的面向服务的应用程序设置所有SSL显示业务:S - perepm
1
使用RUN命令会将证书和密钥的部分包含在镜像中。因此,任何能够拉取镜像的人都可以冒充你。(显然,自签名证书的价值不高,在大多数测试环境中,客户端可能“只是信任它们”)。在CMD/ENTRYPOINT中执行此操作可以更好地避免在镜像中泄露密钥,但这也意味着客户端即使想要知道正确的证书,也无法知道,只能“只是信任它们”。但是,密钥和证书必须一起生成:-( 我怀疑最好的方法是在外部生成并通过挂载卷/环境变量传递。 - undefined
@BeniCherniavsky-Paskin 如果您在生产系统上,可以使用letsencrypt来维护证书,并将其保存到使用volume标志挂载的位置。此外,自签名证书在浏览器中会被标记为“未知颁发者”或其他类似信息。OP之所以问到自签名证书,是因为他们在CI中使用它,所以安全性取决于DevOps人员正确维护它。 - undefined

14

我在nginx:alpine中使用了相似的东西:

FROM nginx:1.19.1-alpine

RUN apk update && \
    apk add --no-cache openssl && \
    openssl req -x509 -nodes -days 365 \
    -subj  "/C=CA/ST=QC/O=Company Inc/CN=example.com" \
     -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key \
     -out /etc/ssl/certs/nginx-selfsigned.crt;

1
受到Kevin Kopf的启发
#!/bin/bash
set -e

OPENSSL_INSTALLED=false

if which openssl >/dev/null
then 
  OPENSSL_INSTALLED=true
fi

## certificate parameters
COUNTRY_NAME="US"
STATE_NAME="New Mexico"
LOCALITY_NAME="Roswell"
ORGANIZATION_NAME="ACME Co, LLC."
ORGANIZATIONAL_UNIT_NAME="ACME Department"
COMMON_NAME="www.domain.com"
EMAIL_ADDRESS="email@domain"

## apache or nginx
SERVER_KEY="apache-selfsigned.key"
SERVER_KEY_PATH="/etc/ssl/private"
SERVER_CRT="apache-selfsigned.crt"
SERVER_CRT_PATH="/etc/ssl/certs"

OPENSSL_SUBJ_OPTIONS="
Country Name (2 letter code) [AU]:$COUNTRY_NAME
State or Province Name (full name) [Some-State]:$STATE_NAME
Locality Name (eg, city) []:$LOCALITY_NAME
Organization Name (eg, company) [Internet Widgits Pty Ltd]:$ORGANIZATION_NAME
Organizational Unit Name (eg, section) []:$ORGANIZATIONAL_UNIT_NAME
Common Name (e.g. server FQDN or YOUR name) []:$COMMON_NAME
Email Address []:$EMAIL_ADDRESS
"

if [ "$OPENSSL_INSTALLED" = true ]
then 
    echo "generating self signed certificate"
    echo "with these options: "
    echo "$OPENSSL_SUBJ_OPTIONS"
    echo ""

    ## generate self signed certificate
    openssl req \
        -new \
        -newkey rsa:4096 \
        -days 365 \
        -nodes \
        -x509 \
        -subj "/emailAddress=$EMAIL_ADDRESS/C=$COUNTRY_NAME/ST=$STATE_NAME/L=$LOCALITY_NAME/O=$ORGANIZATION_NAME/OU=$ORGANIZATIONAL_UNIT_NAME/CN=$COMMON_NAME" \
        -keyout $SERVER_KEY \
        -out $SERVER_CRT
    
    ## uncomment: move to correct location
    #mv -f $SERVER_KEY $SERVER_KEY_PATH/$SERVER_KEY
    #mv -f $SERVER_CRT $SERVER_CRT_PATH/$SERVER_CRT
else
    echo "openssl is not installed"
    exit 1
fi

#end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接