Self-Hosted Github ActionsとAnsibleで研究室のサーバーへのユーザー追加を自動化する

はじめに

研究室のサーバ係として、サーバー運用を少しでも改善したいというモチベーションから、題目にある機能を実装したいと考えた。

私の研究室のサーバー環境としては、VPNに参加した共同のGPUサーバーが複数台(10台近く)設置されている。

研究室メンバーの共同GPUサーバーに対するアクセスは、サーバー係が各GPUサーバーに対して手動でuseradd <ユーザ名>コマンドを打ち、メンバーにパスワードとユーザー名を渡すことで実現されていた。

見ての通り、このようにサーバー係が各GPUサーバーに対して手動でユーザーを発行するのは、非常にめんどくさいのみならず、ユーザープロビジョニングがなされていない、つまり、誰がどのサーバーにアクセス権があるかわからないというような状態にあるという点で非常に問題であると感じた。

このような背景から、研究室の共同Githubを使って、ユーザーの追加/削除をコードで管理しようという発想にいたった。

概観

今回実装したいと考える機能の全体像は以下のようになる。 f:id:yuichinagapan:20211128022149p:plain

  • 研究室共同のGithubレポジトリにユーザーの情報をまとめて管理しておく。
  • GithubからActionsを走らせることにより、研究室内のGPUサーバー全てに対して一括でユーザーの追加/削除が可能。
  • ユーザーの追加/削除にはAnsibleを用いる。
  • Github Actionsは研究室VPNにあるサーバーでSelf-Hostedで走らせる。

実装

環境構築

1. 全ての共同サーバでのsudo権限をもつAnsibleユーザーを手動で発行

sudo useradd -s /bin/bash -m ansible
sudo passwd ansible
sudo usermod -aG sudo ansible

2. 共同サーバーのうち一つのサーバーにおいてSelf-Hosted Runnerを設置する

self-hosted runnerの設置については、公式ドキュメントを参照すると良い。 注意点としては、1のステップで発行したAnsibleユーザーの配下でself-hosted runnerを設置するということである。

docs.github.com

3. Slef-HostedのサーバーにAnsibleをインストール

sudo apt update 
sudo apt install ansible

4. Slef-Hostedのサーバーからパスワードなしで(i.e.公開鍵認証で)他の共同サーバーに接続できるようにする

Self-Hostedのサーバーで下記のコマンドを実行する。

ssh ansible@<self-hostedのサーバー>
cd .ssh
cat <公開鍵>

公開鍵を何処かにメモっておく。

Self-Hostedのサーバー以外で下記のコマンドを実行する。

ssh ansible@<self-hosted以外のサーバー>
cd .ssh
echo "<Self Hosted runnerの公開鍵>" >>  authorized_keys
chmod 600 authorized_keys

5. Self-Hostedサーバーから他のサーバーにansibleユーザーで接続したのち、sudoになるためのパスワードをGithubのSecretsを使って環境変数に設定する。

[Settings]→[Secrets]→[New Repository Secret]

Key: SUDO_PASSWD
Value: <Ansibleユーザーのパスワード>

コード

GitHub - YuichiNAGAO/server-user-management

ディレクトリ構成

├── .github
│   └── workflows
│       ├── add-users.yml
│       └── delete-users.yml
└── user-management
    ├── add-users.yml
    ├── delete-users.yml
    ├── hosts
    ├── list-users
    │   ├── add-users-list.yaml
    │   └── delete-users-list.yaml
    └── roles
        ├── add-users
        │   └── tasks
        │       └── main.yaml
        └── delete-users
            └── tasks
                └── main.yaml

.github/workflows/*: ユーザーの削除と追加の二つのワークフローを用意

user-management/hosts: ユーザーを追加したいサーバーのIPアドレスを記入

user-management/list-users/*: 追加したいユーザーのリストと削除したいユーザーのリストをyamlファイル形式で保持

add-users-list.yaml

user_info:
  - user_name: "test"
    public_key: "公開鍵"
  - user_name: "test2"
    public_key: "公開鍵"

delete-users-list.yaml

user_info:
  - user_name: "test"
  - user_name: "test2"

操作

ユーザーの追加

  1. 追加したいユーザーの公開鍵を取得する
  2. 公開鍵を入手したら、list-users/配下のadd-users-list.yamlを編集してユーザー情報を追加する。
  3. Github Actionsでadd-users.ymlのワークフローを手動でトリガーする。
  4. ワークフローがエラーなく完了したら、全てのGPUサーバーへのユーザー追加が完了する。

ユーザーの削除

  1. 追加したいユーザー名を取得する。
  2. list-users/配下のdelete-users-list.yamlを編集してユーザー情報を追加する。
  3. Github Actionsでadd-users.ymlのワークフローを手動でトリガーする。誤作動防止のため"delete"と入力しないとワークフローが走らないように設定されている。
  4. ワークフローがエラーなく完了したら、全てのGPUサーバーにおけるユーザーの削除が完了する。*削除のワークフローを実行すると、ユーザーのホームディレクトリも削除されてしまうので、実行には十分注意する。

終わりに

Githubレポジトリのyamlファイルの編集をし、Github Actionsのワークフローをトリガーするだけで、ユーザーの一括追加/削除が可能となった。