2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

STNS環境でrootlessコンテナを実行するためのsubuidとsubgidを追加する

Posted at

はじめに

rootlessコンテナを実行する際にsubuidとsubgidがある前提で進めている記事があります.しかし,subuidとsubgidの追加方法について載っている記事はなかなか見つけにくいです.

STNS(Simple Toml Name Service)1はTOML(Tom's Obvious, Minimal Language.)2ベースの構成でLinuxユーザーを簡単に管理できるOSS(Open Source Software)です.STNSがあれば,複数のサーバー1つ1つにauthorized_keysを設定しなくてもSSH公開鍵認証でアクセスすることができるようになります.

環境

  • Ubuntu 22.04.2 LTS
    • lsb_release -a3
  • STNS v2.2.12-1
    • apt list --installed | grep stns4

問題点

STNSを用いてユーザー管理をしている場合,初めてログインしたユーザーにホームディレクトリを作成する方法があります.

以下を/etc/pam.d/sshdの末尾に追加することでホームディレクトリを自動で作成することができます5

/etc/pam.d/sshd
session    required     pam_mkhomedir.so skel=/etc/skel/ umask=0022

この方法では,uid,gidはSTNSで作成できてもsubuid,subgidが生成されません.
実際に以下のコマンドで何も出力されない場合はsubuid,subgidがありません.

$ grep $USER /etc/subuid /etc/subgid

解決策

ログインした際にsubuidとsubgidを生成するshell scriptを/etc/bash.bashrcに追記します.subuidとsubgidの生成にはusermod6コマンドを使用します.

追記する内容は以下に載せます.

/etc/bash.bashrc
# 1. 登録されたsubuidから1番うしろのsubuidを取得
ID_FILE='/etc/subuid'
LASTID=`cat ${ID_FILE} | tail -n 1 | cut -f 2 -d ":"`

# 2. 登録するsubuidとsubgidの始まりの値の決定
if [ -z "$LASTID" ]; then
HEADID=100000
else
HEADID=$(($LASTID + 65536))
fi

# 3. 登録するsubuidとsubgidの終わりの値の決定
TAILID=$(($HEADID + 65535))

# 4. subuidとsubgidの登録
USERID=`grep $USER /etc/subuid | cut -f 1 -d ":"`
if [ ! "$USER" = "$USERID" ]; then
sudo usermod -v "$HEADID""-""$TAILID" -w "$HEADID""-""$TAILID" $USER
echo "Create subuid & subgid: ""$HEADID""-""$TAILID"
fi

subuidとsubgidの確認

$ grep $USER /etc/subuid /etc/subgid
/etc/subuid:g212200344:1410720:65536
/etc/subgid:g212200344:1410720:65536

このようにsubuidとsubgidが出力されれば成功です!


ここから下は解説


解説

やっていることの解説をします.

  1. 登録されたsubuidから一番うしろのsubuidを取得
  2. 登録するsubuidとsubgidの始まりの値の決定
  3. 登録するsubuidとsubgidの終わりの値の決定
  4. subuidとsubgidの登録

変数と言葉の対応関係

HEADID:登録するIDの始まりの値
TAILID:登録するIDの終わりの値

1. 登録されたsubuidから1番うしろのsubuidを取得

subuidが記録しているファイルから1番うしろの行のsubuidを取得します.コマンドで説明すると,cat7 8でファイルの内容を取得し,tailで最後の1行を取り出し,cutで":"で分けた2つ目の要素を取り出します.

2. 登録するsubuidとsubgidの始まりの値の決定

1.で出力したIDに何も入っていない際9は,登録するIDの始まりの値を100000にします.Ubuntuはuseraddadduserコマンドでユーザーを追加した際にsubuidとsubgidの始まりの値を100000と設定するため,それに合わせています.

もし,1.で出力したIDがあった際はIDとして必要な範囲,65535の次の値である65536を足した値を登録するIDの始まりの値にします.Ubuntuはuseraddadduserコマンドでユーザーを追加した際の値に合わせています.rootlessコンテナではapt-getを実行した際は65534番を使用しているので,同じように割り当てられているものが65535個あるのでしょう.

subuidとsubgidの範囲が足りない際にapt-getすると以下のようなエラーが出ると思います.

[error]
setgroups 65534 error
setegid 65534 error

3. 登録するsubuidとsubgidの終わりの値の決定

65535個のsubuidとsubgidのIDを割り当てるので,登録するIDの始まりの値から65535足した[^7]値を登録するIDの終わりの値とする.

4. subuidとsubgidの登録

subuidが記録しているファイルからsubuidが割り振られているか確認する10.subuidが割り振られている際は登録せずに処理を追える.subuidが割り振られていない際はusermodコマンドでsubuidとsubgidを登録する.最後にsubuidとsubgidが新しく割り振られた際はSSH公開鍵認証でアクセスしたターミナルに新しくsubuidとsubgidが割り振られたことを表示する.

おまけ ~Ansibleでsubgidとsubuidを登録できるようにするには?~

1つ1つサーバーにログインして先程の/etc/bash.bashrcに追記するのは骨が折れると思います.なので,Ansible(IT自動化ツールの1つ)でぱぱっと入れちゃいたい人用のyaml(YAML Ain't Markup Language)ファイルを載せておきます.

add_sub_uid_gid.yaml
- hosts: all
  tasks:
    - name: Copy sshrc file
      become: true
      ansible.builtin.blockinfile:
        path: /etc/bash.bashrc
        block: |
          ID_FILE='/etc/subuid'
          LASTID=`cat ${ID_FILE} | tail -n 1 | cut -f 2 -d ":"`
          if [ -z "$LASTID" ]; then
            LASTID=100000
          else
            LASTID=$(($LASTID + 65536))
          fi
          USERID=`grep $USER /etc/subuid | cut -f 1 -d ":"`
          TAILID=$(($LASTID + 65535))
          if [ ! "$USER" = "$USERID" ]; then
            sudo usermod -v "$LASTID""-""$TAILID" -w "$LASTID""-""$TAILID" $USER
            echo "Create subuid & subgid: ""$LASTID""-""$TAILID"
          fi
        state: present
    - name: Remove subuid
      become: true
      ansible.builtin.file:
        path: /etc/subuid
        state: absent
    - name: Remove subgid
      become: true
      ansible.builtin.file:
        path: /etc/subgid
        state: absent
    - name: Make subuid file
      become: true
      ansible.builtin.file:
        path: /etc/subuid
        state: touch
    - name: Make subgid file
      become: true
      ansible.builtin.file:
        path: /etc/subgid
        state: touch

hostファイルに宛先を書いておきます.sre001.localからsre003.localへ実行したい場合のhostsファイルを載せます.

hosts
sre001.local
sre002.local
sre003.local

実行コマンドです.

$ ansible-playbook -i hosts add_sub_uid_gid.yaml --ask-become-pass

[^7]今どきのシェルスクリプトは数値計算にexprを使わない(POSIX準拠) - Qiita

  1. STNS

  2. GitHub - toml-lang/toml: Tom's Obvious, Minimal Language

  3. Ubuntuのバージョンを確認する方法 | server-memo.net

  4. 【apt】コマンド(応用編)-パッケージを検索する:Linux基本コマンドTips(140) - @IT

  5. ssh接続が成功した時ににホームディレクトリを自動生成する - cameong’s blog

  6. 1.7. ルートレスコンテナーへのアップグレード Red Hat Enterprise Linux 8

  7. フィルタを使用した文字列操作 2 | UNIX & Linux コマンド・シェルスクリプト リファレンス

  8. cutコマンドについてまとめました 【Linuxコマンド集】

  9. シェルで変数の空文字判定 | クロジカ

  10. シェルスクリプトで文字列や数値が一致するか判断する

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?