2021年4月3日土曜日

docker registry の auth token ではどのようなトークン情報が送信されるのか確認してみた

docker registry の auth token ではどのようなトークン情報が送信されるのか確認してみた

概要

docker の token 認証を使った場合にどのようなリクエストが docker registry 側から飛んでくるのかを確認したくてダミーの認証サーバを作成して確認してみました

環境

  • macOS 11.2.3
  • docker 20.10.5
  • Ruby 3.0.0

自己署名した SSL 証明書の作成

  • openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/CN=Registry Auth CA"
  • openssl x509 -outform pem -in RootCA.pem -out RootCA.crt

サーバ SSL 証明書でなければいけません
認証サーバから送られてきたトークン情報を証明書を使って復号化してチェックするためです
今回は registry から送信される情報を確認するだけなので認証サーバで正常なトークンの生成などは行いません
ちなみに証明書が SSL 用でなかったり正常に作成されていないと registry 起動時に 「token auth requires at least one token signing root certificate」というエラーが表示されます

docker registry 用の設定ファイル作成

auth.token の設定を行います
先程作成した RootCA.crt を使うように設定します

version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
  delete:
    enabled: true
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
auth:
  token:
    realm: http://host.docker.internal:4567/jwt/auth
    service: container_registry
    issuer: gitlab-issuer
    rootcertbundle: /home/RootCA.crt

realm はダミー認証サーバのエンドポイントを指定します
今回は mac 上で動作させるのと Sinatra を予定しているので上記のエンドポイントを指定します

docker registry 起動

作成した設定ファイルと証明書をマウントするように起動します

  • docker run -d -p 5000:5000 -v $(pwd)/config.yml:/etc/docker/registry/config.yml -v $(pwd)/RootCA.crt:/home/RootCA.crt registry:2

リクエストを確認するためのダミー認証サーバの作成

先程説明したように Sinatra で作成します
設定ファイルに記載したとおり /jwt/auth で受けるようにします

  • vim app.rb
require 'sinatra'
require "sinatra/json"

get '/jwt/auth' do
  logger.info params
  logger.info request.env.select {|k,v| k.start_with? "HTTP_" }
  'auth error'
end

今回はレスポンスを適当に返しているので認証は必ずエラーになります
これでどんなリクエストが registry の token 認証時に送信されているのかが確認できます

動作確認

  • bundle exec ruby app.rb -o 0.0.0.0
  • docker login localhost:5000

これでログインしてみると以下のようなログが表示されると思います

I, [2021-04-01T10:22:30.046322 #51291]  INFO -- : {"account"=>"root", "client_id"=>"docker", "offline_token"=>"true", "service"=>"container_registry"}
I, [2021-04-01T10:22:30.046940 #51291]  INFO -- : {"HTTP_VERSION"=>"HTTP/1.1", "HTTP_ACCEPT_ENCODING"=>"gzip", "HTTP_AUTHORIZATION"=>"Basic cm9vdDph", "HTTP_CONNECTION"=>"close", "HTTP_HOST"=>"host.docker.internal:4567", "HTTP_USER_AGENT"=>"docker/20.10.5 go/go1.13.15 git-commit/363e9a8 kernel/4.19.121-linuxkit os/linux arch/amd64 UpstreamClient(Docker-Client/20.10.5 \\(darwin\\))"}
127.0.0.1 - - [01/Apr/2021:10:22:30 +0900] "GET /jwt/auth?account=root&client_id=docker&offline_token=true&service=container_registry HTTP/1.1" 200 10 0.0096

認証サーバ側では account や HTTP_AUTHORIZATION の情報を使ってデータベースなどと照合してログイン情報が合っているのかを確認する感じになります
あとは scope などの認可判定なども実装する必要があります

最後に

docker registry の token 時にどのようなリクエストが来るのかをダミーの認証サーバを構築して確認してみました
実際はこれらのリクエスト情報を元に実際に認証するような仕組みを開発する必要があります
自前で作るのが面倒な場合は docker_auth という簡単に構築できる認証サーバもあるのでこれを使ってもよいと思います

参考サイト

0 件のコメント:

コメントを投稿