From 8615cbf2862b493f594498efd24f3377e7b33b50 Mon Sep 17 00:00:00 2001 From: khs1994 Date: Mon, 11 Dec 2017 20:22:51 +0800 Subject: [PATCH] Add registry auth TLS #180 --- CHANGELOG.md | 2 + SUMMARY.md | 1 + repository/demo/auth/nginx.htpasswd | 2 + repository/demo/config.yml | 35 ++++ repository/demo/docker-compose.yml | 13 ++ repository/demo/root-ca.cnf | 4 + repository/demo/site.cnf | 7 + repository/demo/ssl/docker.domain.com.crt | 35 ++++ repository/demo/ssl/docker.domain.com.key | 51 ++++++ repository/registry.md | 2 +- repository/registry_auth.md | 210 ++++++++++++++++++++++ 11 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 repository/demo/auth/nginx.htpasswd create mode 100644 repository/demo/config.yml create mode 100644 repository/demo/docker-compose.yml create mode 100644 repository/demo/root-ca.cnf create mode 100644 repository/demo/site.cnf create mode 100644 repository/demo/ssl/docker.domain.com.crt create mode 100644 repository/demo/ssl/docker.domain.com.key create mode 100644 repository/registry_auth.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 1326ad7..9971572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * 0.9-rc3: 2017-12-20 + * 增加 `私有仓库高级配置` + * 精简示例代码 * 调整目录结构 diff --git a/SUMMARY.md b/SUMMARY.md index 18a4764..ffab2bf 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -51,6 +51,7 @@ * [访问仓库](repository/README.md) * [Docker Hub](repository/dockerhub.md) * [私有仓库](repository/registry.md) + * [私有仓库高级配置](repository/registry_auth.md) * [数据管理](data_management/README.md) * [数据卷](data_management/volume.md) * [监听主机目录](data_management/bind-mounts.md) diff --git a/repository/demo/auth/nginx.htpasswd b/repository/demo/auth/nginx.htpasswd new file mode 100644 index 0000000..4a9e7f9 --- /dev/null +++ b/repository/demo/auth/nginx.htpasswd @@ -0,0 +1,2 @@ +username:$2y$05$TRWvCC6ilpKpY3ICifw32Ok3.8SpG3etq8O5WGdCm9wvyDhtSbRgy + diff --git a/repository/demo/config.yml b/repository/demo/config.yml new file mode 100644 index 0000000..086ac0b --- /dev/null +++ b/repository/demo/config.yml @@ -0,0 +1,35 @@ +version: 0.1 +log: + accesslog: + disabled: true + level: debug + formatter: text + fields: + service: registry + environment: staging +storage: + delete: + enabled: true + cache: + blobdescriptor: inmemory + filesystem: + rootdirectory: /var/lib/registry +auth: + htpasswd: + realm: basic-realm + path: /etc/docker/registry/auth/nginx.htpasswd +http: + addr: :5000 + host: https://docker.domain.com + headers: + X-Content-Type-Options: [nosniff] + http2: + disabled: false + tls: + certificate: /etc/docker/registry/ssl/docker.domain.com.crt + key: /etc/docker/registry/ssl/docker.domain.com.key +health: + storagedriver: + enabled: true + interval: 10s +threshold: 3 diff --git a/repository/demo/docker-compose.yml b/repository/demo/docker-compose.yml new file mode 100644 index 0000000..86820de --- /dev/null +++ b/repository/demo/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3' + +services: + registry: + image: registry + ports: + - "443:5000" + volumes: + - ./:/etc/docker/registry + - registry-data:/var/lib/registry + +volumes: + registry-data: diff --git a/repository/demo/root-ca.cnf b/repository/demo/root-ca.cnf new file mode 100644 index 0000000..b87de32 --- /dev/null +++ b/repository/demo/root-ca.cnf @@ -0,0 +1,4 @@ +[root_ca] +basicConstraints = critical,CA:TRUE,pathlen:1 +keyUsage = critical, nonRepudiation, cRLSign, keyCertSign +subjectKeyIdentifier=hash diff --git a/repository/demo/site.cnf b/repository/demo/site.cnf new file mode 100644 index 0000000..608538b --- /dev/null +++ b/repository/demo/site.cnf @@ -0,0 +1,7 @@ +[server] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:docker.domain.com, IP:127.0.0.1 +subjectKeyIdentifier=hash diff --git a/repository/demo/ssl/docker.domain.com.crt b/repository/demo/ssl/docker.domain.com.crt new file mode 100644 index 0000000..a88a837 --- /dev/null +++ b/repository/demo/ssl/docker.domain.com.crt @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +MIIF/zCCA+egAwIBAgIJAMbgVbFo7I6IMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV +BAYTAkNOMQ8wDQYDVQQIDAZTaGFueGkxDzANBgNVBAcMBkRhdG9uZzEaMBgGA1UE +CgwRWW91ciBDb21wYW55IE5hbWUxLTArBgNVBAMMJFlvdXIgQ29tcGFueSBOYW1l +IERvY2tlciBSZWdpc3RyeSBDQTAeFw0xNzEyMTExMTI2NTRaFw0xOTEyMzExMTI2 +NTRaMGcxCzAJBgNVBAYTAkNOMQ8wDQYDVQQIDAZTaGFueGkxDzANBgNVBAcMBkRh +dG9uZzEaMBgGA1UECgwRWW91ciBDb21wYW55IE5hbWUxGjAYBgNVBAMMEWRvY2tl +ci5kb21haW4uY29tMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1Hbm +1tZvAeC8J54pQLHTVCtrICQ8KFTLOZakPHSWox8iQ4i2fkZaSccvE/51LIFnCM1y +yZv88ILucqitG4zvuhDG+cU8w1vRbWf3xfGCCsHyn6LKBHR0Kk6+WRIBZTdRSsW8 +ZvpL2Y7eBNAUkC2oeaOJEOQ8D50b3u5jhAFmXuAcTiZh90Ve4JBKZV8dGs8L81vO +vb7tqvJrEvCNKuZO7mEcjXkgiwUdP3pkZYa0tPOV5UrLH/oEvgPDJfXrNntCY1+A ++CBQ7Sq3S2YpNJN7VnK6SboRi7xpOEgQOXwNVJWm/5YBvnbAztNXKcE2q2wREL9T +ulUJCqo2h6NRaGYPfiLZIUHEJ7vQitRBRDpkxcX8XJX3Jm7weRPXLDOG8RN3FzPD +TGL2ZDTWKDIQ20OhYEmENInKkpC2bYpwMzNvBA7AJN6MCYHXl4VP/Df0pPtMM/Di +ZX+68ng3RQXT5VzDYURIH2wP5kcTL0irsNr+L7lHD+5mA1VErdQsh6AHWjrwMrSM +egJpLP11rK4J+P/HHnqsBEi5XZI/hvRmwD7gwskRqXdDMHaWnoIIpPO3TeNYQUjD +xaV5KUQuWVME5Ihuy03FPMChXXB0WF+tclPJxjQyDkwEVL+6d8i5yCPUBS2gBSBy +pQQINFH4hOcx2e9Lujx7dOWfidjX3xssC9bEe60CAwEAAaOBmjCBlzAfBgNVHSME +GDAWgBTS1B3CPFKA/HcI0cdE8YD4zG143DAMBgNVHRMBAf8EAjAAMBMGA1UdJQQM +MAoGCCsGAQUFBwMBMA4GA1UdDwEB/wQEAwIFoDAiBgNVHREEGzAZghFkb2NrZXIu +ZG9tYWluLmNvbYcEfwAAATAdBgNVHQ4EFgQUSanj6Cs4KVEKaK6/+VA/fNwNg4Ew +DQYJKoZIhvcNAQELBQADggIBAKYtI1WKAL4FoSgH6sTZakw6h90uebrxm9ojeZTA +k0ues8bGTu3w3dsphd9J0V27oz/dGjkwoIzy4QMYC4h6epKVadWfDhnHUPUT1JIC +nGl7qFR539CSPzW+J1mVAGTZ1QONVxe6rFEDRXTsm9oUNq9LUB6a9EBO/9O0x2o7 +SZVUJd2WfMGAhqYjKCtMt+8kQgPxayok5IwWLBf03nluoF09Xu1WbY3f9wGNrzQp +ulNlLzkU3f7+dVgF4lvIbr4MPWSQL2A0RYYjqWuwvUlXggtR+Nl6ldotDe7Ae18V +KhQPJzM4muHjRY5dLkzQIIAQifxNprZCYiurUCAmOyOcHYMt5RuiVUPlB/2hoP/E +tuFqq66v0qsE4mCfmJrRq+Yjfgcqsg1quRpjWh9DWOGa9HUeYFkLEKOgXybxVHJQ +ktYba34ZFfBJUMcbZRYrRH6R4zu4LpRiyiXm29F5ml9tarThDZB5g5DJ6BTEt3Zw ++qQHsIAcmHZvJPKEZmM6883gxbGQQ1Xt7iDrp94YRXMguBMbJwEsqI7w+25BHija +Hp4gctdoBvkQBYpXoEsn8wnguofqJt/JhVgu0EQXR4j3U0uI+Oo9ODHFb5t2T26w +EifwcLH+NyUNmUQH45lxaCzb+tqFlP7cbHsdPniaS4AtmBYwKNJMjcrgxnZPtfy1 +7zJA +-----END CERTIFICATE----- diff --git a/repository/demo/ssl/docker.domain.com.key b/repository/demo/ssl/docker.domain.com.key new file mode 100644 index 0000000..4545ed4 --- /dev/null +++ b/repository/demo/ssl/docker.domain.com.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +oKnsMQKCAQEA0iurbnOyrF050SfRdQcnG4shZs/HeBT2EB3CsR1OocWwXBeUkBlO +OKl+d1cYan1ppw+qGlbdQr+t3u7lLPFLUBghf+I/8CmSyiCbZlR4/LrePOmw551r +YXU1uvtFu/mQq3ieV+k4GOyHq3lhCDd61QFedyESfbkVK8f4ihvvX3izZAAtZfwU +HcmZ174vpwZploWQPsrL9A2B+Na42ccLM2qA45nPwXv1Jr/U6b/CzPw7r/4DvTXv +FIeolrELDkCgWBQ8lxB7Lt96BZy9Rbiwi1TzcP++BQu4IOwbAfq23tCybu8vDde4 +Z15KVf7qyBansdqKx0njxWNu2/dpgKCPqQKCAQEAzWV4aajox7eeTi3iudP1Oxu3 +OBiu8xie4xq0mlM13tMxAQry/uOAuTxbaQ48mNsSXdeYeSgmT45lUvFWROqdVScK +8gh04G1NiRAkITzXwCCwKkAQxvQppgypZ+aksBHkFQFBAIg2/mLizS4cicXNEY4G +vb+RImfn8MSqSMLu3cJ8zgFyqfRg6F0oHg9EgEwvbnCLYglN6Xm5KlZutjW4eu7m +Q+1y0lg05e7vFyj2UIVylfzT/aoF/xzXzNt9/LZs0klO3vMmaVyTjuF/71+AyphH +FTmpNs1wpZU2IRqKOMrimIhk6TTxvMSaN4pxKdLPqgHYLWhwkbsdmqtTnCljRg== +-----END RSA PRIVATE KEY----- diff --git a/repository/registry.md b/repository/registry.md index 51d68c4..7010734 100644 --- a/repository/registry.md +++ b/repository/registry.md @@ -95,7 +95,7 @@ REPOSITORY TAG IMAGE ID CREAT 如果你不想使用 `127.0.0.1:5000` 作为仓库地址,比如想让本网段的其他主机也能把镜像推送到私有仓库。你就得把例如 `192.168.199.100:5000` 这样的内网地址作为私有仓库地址,这时你会发现无法成功推送镜像。 -这是因为 Docker 默认不允许非 `HTTPS` 方式推送镜像。我们可以通过 Docker 配置来取消这个限制,或者配置能够通过 `HTTPS` 访问的私有仓库。 +这是因为 Docker 默认不允许非 `HTTPS` 方式推送镜像。我们可以通过 Docker 配置来取消这个限制,或者查看下一节配置能够通过 `HTTPS` 访问的私有仓库。 #### Ubuntu 14.04, Debian 7 Wheezy diff --git a/repository/registry_auth.md b/repository/registry_auth.md new file mode 100644 index 0000000..0a626e8 --- /dev/null +++ b/repository/registry_auth.md @@ -0,0 +1,210 @@ +## 私有仓库高级配置 + +上一节我们搭建了一个具有基础功能的私有仓库,本小节我们来使用 `Docker Compose` 搭建一个拥有权限认证、TLS 的私有仓库。 + +新建一个文件夹,以下步骤均在该文件夹中进行。 + +### 准备站点证书 + +如果你拥有一个域名,国内各大云服务商均提供免费的站点证书。你也可以使用 `openssl` 自行签发证书。 + +这里假设我们将要搭建的私有仓库地址为 `docker.domain.com`,下面我们介绍使用 `openssl` 自行签发 `docker.domain.com` 的站点 SSL 证书。 + +第一步创建 `CA` 私钥。 + +```bash +$ openssl genrsa -out "root-ca.key" 4096 +``` + +第二步利用私钥创建 `CA` 根证书请求文件。 + +```bash +$ openssl req \ + -new -key "root-ca.key" \ + -out "root-ca.csr" -sha256 \ + -subj '/C=CN/ST=Shanxi/L=Datong/O=Your Company Name/CN=Your Company Name Docker Registry CA' +``` + +>以上命令中 `-subj` 参数里的 `/C` 表示国家,如 `CN`;`/ST` 表示省;`/L` 表示城市或者地区;`/O` 表示组织名;`/CN` 通用名称。 + +第三步配置 `CA` 根证书,新建 `root-ca.cnf`。 + +```bash +[root_ca] +basicConstraints = critical,CA:TRUE,pathlen:1 +keyUsage = critical, nonRepudiation, cRLSign, keyCertSign +subjectKeyIdentifier=hash +``` + +第四步签发根证书。 + +```bash +$ openssl x509 -req -days 3650 -in "root-ca.csr" \ + -signkey "root-ca.key" -sha256 -out "root-ca.crt" \ + -extfile "root-ca.cnf" -extensions \ + root_ca +``` + +第五步生成站点 `SSL` 私钥。 + +```bash +$ openssl genrsa -out "docker.domain.com.key" 4096 +``` + +第六步使用私钥生成证书请求文件。 + +```bash +$ openssl req -new -key "docker.domain.com.key" -out "site.csr" -sha256 \ + -subj '/C=CN/ST=Shanxi/L=Datong/O=Your Company Name/CN=docker.domain.com' +``` + +第七步配置证书,新建 `site.cnf` 文件。 + +```bash +[server] +authorityKeyIdentifier=keyid,issuer +basicConstraints = critical,CA:FALSE +extendedKeyUsage=serverAuth +keyUsage = critical, digitalSignature, keyEncipherment +subjectAltName = DNS:docker.domain.com, IP:127.0.0.1 +subjectKeyIdentifier=hash +``` + +第八步签署站点 `SSL` 证书。 + +```bash +$ openssl x509 -req -days 750 -in "site.csr" -sha256 \ + -CA "root-ca.crt" -CAkey "root-ca.key" -CAcreateserial \ + -out "docker.domain.com.crt" -extfile "site.cnf" -extensions server +``` + +这样已经拥有了 `docker.domain.com` 的网站 SSL 私钥 `docker.domain.com.key` 和 SSL 证书 `docker.domain.com.crt`。 + +新建 `ssl` 文件夹并将 `docker.domain.com.key` `docker.domain.com.cer` 这两个文件移入,删除其他文件。 + +### 配置私有仓库 + +私有仓库默认的配置文件位于 `/etc/docker/registry/config.yml`,我们先在本地编辑 `config.yml`,之后挂载到容器中。 + +```yaml +version: 0.1 +log: + accesslog: + disabled: true + level: debug + formatter: text + fields: + service: registry + environment: staging +storage: + delete: + enabled: true + cache: + blobdescriptor: inmemory + filesystem: + rootdirectory: /var/lib/registry +auth: + htpasswd: + realm: basic-realm + path: /etc/docker/registry/auth/nginx.htpasswd +http: + addr: :443 + host: https://docker.domain.com + headers: + X-Content-Type-Options: [nosniff] + http2: + disabled: false + tls: + certificate: /etc/docker/registry/ssl/docker.domain.com.crt + key: /etc/docker/registry/ssl/docker.domain.com.key +health: + storagedriver: + enabled: true + interval: 10s +threshold: 3 +``` + +### 生成 http 认证文件 + +```bash +$ mkdir auth + +$ docker run --rm \ + --entrypoint htpasswd \ + registry \ + -Bbn username password > auth/nginx.htpasswd +``` + +> 将上面的 `username` `password` 替换为你自己的用户名和密码。 + +### 编辑 `docker-compose.yml` + +```yaml +version: '3' + +services: + registry: + image: registry + ports: + - "443:443" + volumes: + - ./:/etc/docker/registry + - registry-data:/var/lib/registry + +volumes: + registry-data: +``` + +### 修改 hosts + +编辑 `/etc/hosts` + +```bash +docker.domain.com 127.0.0.1 +``` + +### 启动 + +```bash +$ docker-compose up -d +``` + +这样我们就搭建好了一个具有权限认证、TLS 的私有仓库,接下来我们测试其功能是否正常。 + +### 测试私有仓库功能 + +登录到私有仓库。 + +```bash +$ docker login docker.domain.com +``` + +尝试推送、拉取镜像。 + +```bash +$ docker pull ubuntu:17.10 + +$ docker tag ubuntu:17.10 docker.domain.com/username/ubuntu:17.10 + +$ docker push docker.domain.com/username/ubuntu:17.10 + +$ docker image rm docker.domain.com/username/ubuntu:17.10 + +$ docker pull docker.domain.com/username/ubuntu:17.10 +``` + +如果我们退出登录,尝试推送镜像。 + +```bash +$ docker logout docker.domain.com + +$ docker push docker.domain.com/username/ubuntu:17.10 + +no basic auth credentials +``` + +发现会提示没有登录,不能将镜像推送到私有仓库中。 + +### 注意事项 + +如果你本机占用了 `443` 端口,你可以配置 [Nginx 代理](https://docs.docker.com/registry/recipes/nginx/),这里不再赘述。