SSHを構築してDocker 09/18に転送する秘Secret

画像

Dockerfileを使用して、プライベートリソースにアクセスすることは常に困難でした。 単に良い解決策はありませんでした。 環境変数を使用したり、使用後に単に秘密ファイルを削除したりするのは良くありません。これらは画像のメタデータに残っています。 ユーザーは時々トリックに行きました。マルチステージアセンブリを作成しましたが、最終段階で秘密の値がなく、クリッピングまで秘密のファイルがローカルアセンブリキャッシュに保存されるように細心の注意を払わなければなりませんでした。







Dockerビルドチーム9月18日には、多くの更新が含まれています。 主な機能は、サーバー側の実装の完全に新しいバージョンが登場したことで、Moby BuildKitプロジェクトの一部として提供されます。 BuildKitサーバーアプリケーションは、Dockerfileビルドシークレットのサポートを含む新しい機能を取得しました。







シークレットを使用する



まず、BuildKitサーバー側を有効にする必要があります。 バージョン18.09



BuildKitは、 DOCKER_BUILDKIT=1



docker build



起動docker build



前にDOCKER_BUILDKIT=1



環境変数を使用して有効にできる選択機能です。 次のバージョンでは、BuildKitをデフォルトでサーバーパーツにする予定です。







 export DOCKER_BUILDKIT=1
      
      





ビルドシークレットの実装は、2つの新しいBuildKit機能に基づいています。 それらの1つは、レジストリ内の画像から読み込まれたユーザーインターフェイスを使用する機能です。 2つ目は、DockerfileのRUN



コマンドでマウントポイントを使用する機能です。 (標準の代わりに)シークレットをサポートする実装関数を使用するには、Dockerfileの最初の行にある構文ディレクティブを使用してリンカーイメージを定義します-使用するコンテナーのイメージを示します。 これまでのところ、外部Dockerfilesの安定したチャネルの秘密は利用できません。例えば、 docker/dockerfile:experimental



またはdocker/dockerfile/1.0.0-experimental



など、実験チャネルのいずれかのバージョンが必要です。







 # syntax=docker/dockerfile:1.0.0-experimental
      
      





Dockerfileの作成者として、DockerfileにインストールされたRUN



コマンドにシークレット値が必要であることを知っている場合、コマンドに必要なシークレットとマウント先を示す--mount



ラベルを使用します。 --mount



ラベルは、 --mount



ようにコンマ区切りの構造を受け入れdocker run









 # syntax=docker/dockerfile:1.0.0-experimental FROM alpine RUN --mount=type=secret,id=mysite.key command-to-run
      
      





このラベルは、操作中にコマンドがパス/run/secrets/mysite.key



沿ってシークレットファイルにアクセスできることを示します。 秘密は、マウントラベルを持つチームのみがアクセスでき、アセンブリの他の部分はアクセスできません。 このファイルのデータは、指定された識別子「mysite.key」に基づいてシークレットストアからダウンロードされます。 Dockerコマンドラインインターフェイスは現在、 --secret



タグを使用してローカルクライアントファイルからのシークレットの開示をサポートしています。







 docker build --secret id=mysite.key,src=path/to/mysite.key .
      
      





上記のように、シークレットはデフォルトで/run/secrets



に設定されますが、「ターゲット」キーを使用して任意のパスを指定できます。 「target」が指定されているが「id」が指定されていない場合、デフォルトでは「id」が宛先パスのベース名になります。







1つの秘密に限定する必要はありません。 それらはいくつでも使用でき、異なる識別子を示します。







Dockerfileの作成者がRUN



命令がシークレットを使用できることを示し、アセンブリを呼び出すユーザーがそれを提供しない場合、シークレットは無視され、指定されたパスにファイルはインストールされません。 この状況が望ましくない場合は、「必須」キーを使用します。これは、値がないとアセンブリが失敗することを示します。







 # syntax=docker/dockerfile:1.0.0-experimental FROM alpine RUN --mount=type=secret,id=mysite.key,required <command-to-run>
      
      





実装



シークレットファイルは、最終イメージまたは次のコマンドでのリークを防ぐために、個別のtmpfsファイルシステムにのみ自動的にインストールされ、ローカルビルドキャッシュに保存されません。







秘密の値もビルドキャッシュの計算から除外されるため、メタデータキャッシュは使用できません。







Ssh



ほとんどの場合、おそらくSSHプロトコルを介してプライベートリポジトリにアクセスしようとします。 はい、秘密要素を使用してアセンブリのSSH秘密キーを公開できますが、より良い解決策があります。 SSHプロトコルは公開キー暗号化を使用します。この設計のおかげで、秘密キーを誰にも開示する必要はありません。 たとえば、SSHで複数のコンピューターを使用する場合、キーを転送する必要はありませんssh-A



プロトコルを介して接続を提供するだけです。







--ssh



docker build



同様の機能を追加しました。そこでは、-- --ssh



ラベルを使用して、既存のSSHエージェント接続またはキーをリンカーに向けることができます。 キー情報を送信する代わりに、Dockerは単にこの可能性をリンカーに通知します。 リンカがSSH経由でリモートサーバーにアクセスする必要がある場合、リンカはクライアントに連絡し、接続に必要な特定のリクエストの確認を求めます。 キー自体はクライアントプログラムから離れず、アクセスが必要なプログラムの完了後、リモート接続を再接続するためのリンカーからのデータは残りません。







SSHプロトコルを介したファイル転送へのアクセスは、 type=ssh



ブロックを指定してSSHへのアクセスを直接要求したDockerfile内のコマンドにのみ許可されます。 他のコマンドには、使用可能なSSHエージェントに関するデータがありません。







また、SSHの別の側面であるTOFUセキュリティモデルの使用にも注意する必要があります。 SSHサーバーに初めて接続するとき、未知のホストに関する情報を要求します。これは、このサーバーでローカルに利用可能な公開鍵がないため、リモートパーティから提供された公開鍵がこのアドレスに対して有効かどうかを確認できないためです。







Dockerfileを使用してアセンブルする場合、このリクエストの正確性を検証できないため、SSHを使用しようとしているコンテナーにサーバーの公開キーが既に存在している必要があります。 この公開鍵を取得する方法はいくつかあります。 たとえば、ベースイメージが提供するか、ビルドコンテキストからコピーします。 より簡単なソリューションが必要な場合は、 ssh–keyscan



プログラムをアセンブリの一部として実行しssh–keyscan



。これにより、ホストの現在の公開キーが読み込まれます。







DockerfileのRUN



コマンドへのSSHアクセスを要求するには、タイプ「ssh」のブロックを指定する必要があります。 次に、プロセス中に、SSHエージェントへの読み取り専用アクセスでソケットがインストールされます。 また、SSHプロトコルを使用するプログラムがこのソケットを自動的に使用するように、 SSH_AUTH_SOCK



環境変数を設定します。







 # syntax=docker/dockerfile:experimental FROM alpine # install ssh client and git RUN apk add --no-cache openssh-client git # download public key for github.com RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts # clone our private repository RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject
      
      





Dockerクライアント側では、 --ssh



ラベル--ssh



使用して、このアセンブリでSSH転送が許可されていること--ssh



示す必要があります。







 docker build --ssh default .
      
      





ラベルは、ローカルSSHエージェントまたは秘密キーのソケットの場所を決定するキー値のペアを受け入れます。 値default=$SSH_AUTH_SOCK



を使用する場合は、ソケットパスを空のままにしておくことができます。







Dockerfileブロックでは、idキーを使用して、同じアセンブリに含まれるさまざまなサーバーを分離することもできます。 たとえば、Dockerfileのさまざまなリポジトリへのアクセスは、異なる展開キーを使用して取得できます。 この場合、Dockerfileでは次を使用します。







 … RUN --mount=type=ssh,id=projecta git clone projecta … RUN --mount=type=ssh,id=projectb git clone projectb …
      
      





--ssh projecta=./projecta.pem --ssh projectb=./projectb.pem



build --ssh projecta=./projecta.pem --ssh projectb=./projectb.pem



クライアントデータを展開します。 実際のキーを指定した場合でも、エージェント接続のみがリンカーに送信され、これらの秘密キーの実際の内容は送信されないことに注意してください。







これで、Docker 18.09のビルドシークレットの新機能のレビューが完了しました。 新しい機能がプロジェクトでDockerfileの機能をより有効に活用し、アセンブリラインのセキュリティレベルを高めることを願っています。








All Articles