Podmanの最もエキサイティングな新機能の1つは、ルートレスコンテナです。ルートレスを使用すると、ほとんどすべてのコンテナーを通常のユーザーとして実行でき、特権が昇格されることはなく、セキュリティ上の大きなメリットがあります。ただし、root権限なしでコンテナを実行するには、制限があります。
ユーザーがこれらの1つについて質問しました:ルートレスポッドマンで特定の画像を取得できなかったのはなぜですか?
以下のように、ダウンロード後に画像がエラーをスローしていました:
ERRO[0005] Error pulling image ref //testimg:latest: Error committing the finished image: error adding layer with blob "sha256:caed8f108bf6721dc2709407ecad964c83a31c8008a6a21826aa4ab995df5502": Error processing tar file(exit status 1): there might not be enough IDs available in the namespace (requested 4000000:4000000 for /testfile): lchown /testfile: invalid argument
彼らの問題は、65536を超えるUIDが所有するファイルが画像に含まれていることであると説明しました。この問題により、画像はルートレスPodmanのデフォルトのUIDマッピングに適合せず、使用可能なUIDとGIDの数が制限されます。
それに続く質問は、当然、次のとおりでした。
- なぜその制限が存在するのですか?
- ルートレスモードで通常のPodmanで動作する画像を使用できないのはなぜですか?
- 使用中の正確なUIDとGIDが重要なのはなぜですか?
まず、ホストとは異なるUIDとGIDを使用する必要がある理由を説明し、次にデフォルトが65536である理由と、この数を変更する方法を説明します。
ルートレスコンテナは、ユーザー名前空間内で実行されます 、これは、ホストのユーザーとグループをコンテナにマッピングする方法です。デフォルトでは、Podmanを起動したユーザーをルートレスコンテナのUID /GID0としてマッピングします。
私のシステムでは、私のユーザー(mheon
)はUID1000です。ルートレスコンテナをmheon
として起動すると podman run -t -i --rm fedora bash
を使用 、次にtop
を実行します コンテナ内では、私はUID0-ルートのようです。
ただし、ホストでは、bash
プロセスはまだ私のユーザーによって所有されています。 podman top
を実行すると、この結果を確認できます。 ホストシステム:
mheon@Agincourt code/podman.io (release_blog_1.5.0)$ podman top -l user group huser hgroup
USER GROUP HUSER HGROUP
root root 1000 1000
USER
およびGROUP
オプションは、コンテナに表示されるユーザーとグループです。 、HUSER
およびHGROUP
オプションは、ホストに表示されるユーザーとグループです。 。
簡単な例を示しましょう。 /etc/
をマウントします 、rootが所有するファイルでいっぱいの、rootlessコンテナに入れます。次に、その内容をls
で表示します :
mheon@Agincourt code/libpod (master)$ podman run -t -i -v /etc/:/testdir --rm fedora sh -c 'ls -l /testdir 2> /dev/null | head -n 10'
total 1700
-rw-r--r--. 1 nobody nobody 4664 May 3 14:39 DIR_COLORS
-rw-r--r--. 1 nobody nobody 5342 May 3 14:39 DIR_COLORS.256color
私はコンテナにルートしているにもかかわらず、これらのファイルを変更する権限がありません。それらの多くを見ることさえできません:2> /dev/null
に注意してください ls
の後 エラーをリストしようとしても多くの権限エラーが発生するため、エラーを潰します。
ホストでは、これらのファイルはルートUID 0によって所有されていますが、コンテナでは、nobody
によって所有されています。 。これは、Linuxカーネルが、ファイルを実際に所有しているユーザーがユーザー名前空間に存在しないことを示すために使用する特別な名前です。ホスト上のUIDとGID0はコンテナにマッピングされないため、ファイルが0:0
によって所有される代わりに 、nobody:nobody
が所有しています コンテナの観点から。
ルートレスコンテナにいるように見えるユーザーに関係なく、自分のユーザーとして機能し、ホスト上のユーザーがアクセスできるファイルにのみアクセスできます。この設定は、rootなしのコンテナのセキュリティ上の魅力の大部分を占めています。攻撃者がコンテナから抜け出すことができたとしても、root以外のユーザーアカウントに限定されます。
ユーザー名前空間は、ホスト上のユーザーをコンテナー内のユーザーにマップすることを先に述べ、そのプロセスがコンテナー内のルートに対してどのように機能するかについて少し説明しました。ただし、コンテナには通常、root以外のユーザーがいます。つまり、Podmanは、1つ以上のユーザーがコンテナに存在できるように、追加のUIDにマッピングする必要があります。
つまり、コンテナに必要なすべてのユーザーをマッピングする必要があります。この問題により、イメージがユーザー名前空間で定義されていないUID / GIDを使用したため、上記の元のエラーが発生しました。
newuidmap
およびnewgidmap
実行可能ファイル。通常はshadow-utils
によって提供されます。 またはuidmap
パッケージは、これらのUIDとGIDをコンテナのユーザー名前空間にマッピングするために使用されます。これらのツールは、/etc/subuid
で定義されたマッピングを読み取ります および/etc/subgid
それらを使用して、コンテナーにユーザー名前空間を作成します。これらのsetuid
バイナリは追加された権限を使用して、ルートレスコンテナに追加のUIDとGIDへのアクセスを許可します。これは通常は許可されていません。ルートレスPodmanを実行しているすべてのユーザーは、複数のUIDを持つコンテナーを実行する必要がある場合、これらのファイルにエントリを持っている必要があります。各コンテナはデフォルトで使用可能なすべてのUIDを使用しますが、正確なマッピングは--uidmap
で調整できます。 および--gidmap
。
Linuxの通常の非rootユーザーは、通常、自分のユーザー(1つのUID)にしかアクセスできません。ルートレスコンテナで追加のUIDとGIDを使用すると、通常はroot権限が必要な別のユーザーとして機能できます(または、パスワードを使用して他のユーザーとしてログインします)。マッピング実行可能ファイルnewuidmap
およびnewgidmap
昇格された権限を使用して、/etc/subuid
で構成されたマッピングに従って追加のUIDとGIDへのアクセスを許可します および/etc/subgid
ルートである必要も、ユーザーとしてログインする権限もありません。
ルートレスPodmanを実行しているすべてのユーザーは、複数のUIDを含むコンテナーを実行する必要がある場合、これらのファイルにエントリを持っている必要があります。
次に、コンテナで使用可能なUIDとGIDのデフォルト数の問題:65536です。この数は厳しい制限ではなく、前述の/etc/subuid
を使用して上下に調整できます。 および/etc/subgid
ファイル。
たとえば、私のシステムでは:
mheon@Agincourt code/libpod (master)$ cat /etc/subuid
mheon:100000:65536
このファイルの形式は、<username>:<start_uid>:<size>
です。 、ここでstart_uid
ユーザーが利用できる最初のUIDまたはGIDであり、size
使用可能なUID/GIDの数です(start_uid
から始まります) 、start_uid + size - 1
で終了します 。
その65536をたとえば123456に置き換えると、ルートレスコンテナ内で123456UIDを使用できるようになります。
「デフォルトに65536を選択するのはなぜですか?」 Linuxユーザー作成ツールuseradd
のメンテナーへの質問です。 、初期デフォルトは、Podmanではなく、ユーザーの作成時に入力されるためです。ただし、この設定でほとんどのアプリケーションを変更せずに機能させるのに十分であると推測するのは危険です(非常に古いバージョンのLinuxには16ビットのUID / GIDしかなく、それより高い値はまだやや一般的ではありません)。
注: /etc/subuid
および/etc/subgid
ファイルは、既存のユーザーを調整するためのものです。新規ユーザーのデフォルトは他の場所で調整されます。
新規ユーザーが受け取る65536のデフォルトはハードコーディングされていません。ただし、これは既存のユーザーには影響しません。 /etc/login.defs
で設定されます SUB_UID_COUNT
を含むファイル およびSUB_GID_COUNT
オプション。ほとんどのコンテナはおそらく1000を少し超えるUID/GIDで正常に機能し、それ以降は無駄になると思われるため、実際にはデフォルトを低くすることについて話し合いました。
重要なことは、この値は、特定の1人のユーザーがルートレスコンテナーを実行するために使用できる、ホストに割り当てられたUID/GIDの範囲を表すことです。このシステムに別のユーザーを追加すると、おそらく165536から始まり、デフォルトでは65536幅の別のUIDが取得されます。
ルートにはこれらの制限を変更する権限がありますが、通常のユーザーにはありません。それ以外の場合は、マッピングをmheon:0:65536
に少し変更できます。 そして、システム上の実際のrootユーザーをrootlessコンテナーにマップします。これにより、システム全体のrootアクセスに簡単にピボットできます。
UIDとGIDの重複を防ぐ
セキュリティの一般的なルールとして、システムUID / GID(通常は1000未満の番号)、理想的にはホストシステムで使用されているUID/GIDをコンテナーに入れないようにします。この方法により、ユーザーがルートレスコンテナを作成するときに、ホスト上のシステムファイルにアクセスできなくなります。
また、各ユーザーが他のユーザーと比較して一意の範囲のUID / GIDを持つようにしたいので、ユーザーをalice
追加できます。 私の/etc/subuid
に 私のユーザーとまったく同じマッピングで(alice:100000:65536
)、しかしその後、アリスは私のルートレスコンテナにアクセスでき、私は彼女にアクセスできます。
前に説明したように、ユーザーの割り当てのサイズを増やすことは可能ですが、セキュリティのためにこれらのルールに従う必要があります。もう一度リストします:
- 1000未満のUID/GIDはありません。
- ホストで使用されている場合、UIDまたはGIDはコンテナに入りません。
- ユーザー間でマッピングを重複させないでください。
最後の1つは、より高いUIDとGIDの割り当てにマッピングしたくない主な理由です。 100,000からUID_MAX
までのすべてを含む、1人のユーザーに大規模な範囲を提供できる可能性があります。 、そして420万を少し超えるUIDを利用できるようにしますが、他のユーザーには何も残されません。
Podman 1.5.0以降では、新しい実験的なオプション(--storage-opt ignore_chown_errors
)が追加されました。 )すべてのUIDとGIDを押しつぶして、単一のユーザー(コンテナーを起動したユーザー)としてコンテナーを実行します。この設定は記事の最初の問題を解決しますが、コンテナに一連の追加の制限を課します。その詳細は別の記事に任せるのが最善です。
ルートレスコンテナに課せられたUIDとGIDの制限は不便な場合がありますが、それらに遭遇することはめったにありません。ほとんどのイメージとコンテナーは、使用可能な65536のUIDとGIDよりもはるかに少ない数を使用します。これらの制限は、ルートレスコンテナのトレードオフの一部であり、セキュリティを大幅に向上させるために、利便性と使いやすさを犠牲にしています。