Docker 私有註冊中心身份認證

注:原文做者是 Alex Ianchici,原文地址是 Docker private registry authenticationhtml

安全已經融入了咱們的生活。咱們鎖門,使用密碼保護咱們的銀行信息,可是一般密碼如此複雜以致於形成咱們很容易忘記它。用常識來保護系統的安全是良好的實踐。這真的很容易呈現,由於它是一個內部的系統,沒有必要啓用身份認證以及安全傳輸,但在咱們當前的遠程工做時代,內部網絡可能十分普遍。node

考慮到這一點,咱們花費了一些時間審查了咱們維護的多種系統,並在這星期,我給咱們的私人 Docker 註冊中心設置了添加身份認證的目標。你也許知道,Docker 註冊沒有提供身份認證的方法。所以咱們決定早期的方案就是在咱們的鏡像倉庫前面加一個身份認證的代理。在咱們的案例中,咱們決定經過 SSL 使用 Nginx 並加上一個內部身份認證 API。nginx

此處輸入圖片的描述

該解決方案的幾個優點:git

  • 容許咱們使用咱們內部的身份驗證 API
  • 能夠給其餘系統重複使用身份認證
  • 能夠經過 Docker 容器實現(咱們使用的容器數量小於 3 個)

我把一個簡單的身份認證服務和一個 Nginx 容器放在一塊兒,咱們能夠在 github 上獲取可用的版本(https://registry.hub.docker.com/u/opendns)。github

簡單的基礎身份認證服務

做爲 Nginx 代理容器的一個參考,咱們使用 NodeJS 構建了一個身份認證 API,很是容易的建立了一個基礎身份認證服務。全部咱們所須要作的就是建立一個真正簡單的 server.js,使用 htpasswd utility 生成一個資格證書文件,而且在一個 Docker 容器中封裝,咱們能夠建立以下 Dockerfileweb

FROM google/nodejs 
ADD . /app 
WORKDIR /app 
RUN npm install http-auth 
EXPOSE 8000 
ENV NODE_PATH /data/node_modules/ 
CMD ["node", "server.js"]

而後咱們測試並部署咱們的服務:docker

ubuntu@trusty-64:/basic-auth# docker build -t opendns/basic-auth-service . 

ubuntu@trusty-64:/basic-auth# docker run --name simple-auth opendns/basic-auth-service 

ubuntu@trusty-64:/basic-auth# docker inspect --format '{{ .NetworkSettings.IPAddress }}' simple-auth 
172.17.0.40 

ubuntu@trusty-64:/basic-auth# curl 172.17.0.40:8000 
401 Unauthorized 

ubuntu@trusty-64:/basic-auth# curl -u testuser:testpassword 172.17.0.40:8000 
User authenticated successfully

你能夠在這裏找到基礎身份認證服務的全部示例代碼,可用的容器在這裏npm

Nginx 身份認證代理

Nginx 代理的關鍵部分是配置文件:ubuntu

# define an /auth section to send the request to an authentication service 

location = /auth { 
    proxy_pass {{auth_backend}}; 
    proxy_pass_request_body off; 
    proxy_set_header Content-Length ""; 
    proxy_set_header X-Original-URI $request_uri;
    proxy_set_header X-Docker-Token ""; 
} 

# use the auth_request directive to redirect all requests to the /auth section above 

location / { 
    proxy_pass {{backend}}; 
    auth_request /auth; 
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504; 
    proxy_buffering off; 
}

使用了 http_auth_request 模塊發送用戶,使用 proxy_pass 指令轉發請求到咱們簡單身份認證服務處理,返回 200 或是 401。 401 受權響應觸發 Docker 客戶端迴應一組使用基自己份驗證的憑據。一旦證書被接受,API 將返回 200。Nginx 能夠發送請求到私有註冊中心,把這兩個容器放在一塊兒:安全

ubuntu@trusty-64:/nginx-auth-proxy# docker run -d --name hello-world hello-world  # run a simple web server that prints out 「Hello world」 

ubuntu@trusty-64:/nginx-auth-proxy# docker inspect --format '{{ .NetworkSettings.IPAddress }}' hello-world 
172.17.0.41 

ubuntu@trusty-64:/nginx-auth-proxy# docker run -d -e AUTH_BACKEND=http://172.17.0.40:8000 -e BACKEND=http://172.17.0.41:8081 -p 0.0.0.0:8080:80 nginx-auth 

ubuntu@trusty-64:/nginx-auth-proxy# curl 0.0.0.0:8080 
<html> 
<head><title>401 Authorization Required</title></head> 
<body bgcolor="white"> 
<center>

<h1>401 Authorization Required</h1>

</center>

<hr>

<center>nginx/1.6.1</center> 
</body> 
</html> 

ubuntu@trusty-64:/nginx-auth-proxy# curl -u testuser:testpassword 0.0.0.0:8080 
Hello world

惟一剩下的事情是給這些容器添加 SSL 證書,而後你就能夠好好的玩耍了。你能夠在這裏找到 Nginx 身份認證代理的代碼,在這裏是可用的容器。使用這個方案須要注意幾件事:

  • 使用基礎認證意味着每一個請求都將訪問身份認證 API
  • 基礎認證意味着你的證書不受阻礙的發送,除非你使用 SSL 加密了你的鏈接。注意:永遠不要在沒有 SSL 的狀況下發送基礎認證證書。Docker 的客戶端和註冊中心不會接受 HTTP 方式的基礎認證
  • 訪問私有註冊中心須要對到身份認證代理的請求作必定限制

該解決方案另一個有趣的附帶影響就是,在私有註冊中心啓用 SSL 已經下降了每一個 pull 請求花費的時間,好比,除非在註冊中心的 URL 上指定了端口,不然在鏈接 80 端口以前,客戶端首先初始化嘗試鏈接 443 端口。

相關文章
相關標籤/搜索