はじめに
stnsを使ってユーザ管理を一元化したので、その構築手順や実装例を紹介します。
STNSとは?
サーバにSSHログインする際に使用する公開鍵をtoml形式のファイル(もしくはstns I/Fを
持ったバックエンド)で提供することで、ユーザの設定状態を一元管理するためのツールです。
各サーバにOSユーザを作成する必要がなく、一元管理でき、利用者の増減(例えば、
入社、部署移動、退職など)を簡単に反映でき、運用の手間を減らせます。
こちらを読めば開発の動機、背景がわかります。
STNSバックエンドを自前で立てる理由
そもそもなぜ自前のバックエンドが必要かというと、stnsには標準でtoml形式でユーザ管理するバックエンドが
同梱されていますが、それを使う場合にtomlファイルをgit等で管理すること(情報の一元管理
)はできますが、
結局各サーバにそのtomlを反映する必要があり、状態の一元管理
は難しい。
(反映自動化してもいいのですが、サーバ数や環境増減の頻度によってはそれでもツライし。。)
そのため、利用者共通(全サービス/サーバ共通)で使うSTNSバックエンドが必要と考えました。
やりたいこと
今回実装したSTNSバックエンド要件です。
- 複数サービス/環境を跨ってユーザ一元管理
- 登録ユーザは全ての環境にログインできる
- (QA/本番等の)環境ごとにsudo可能なユーザを設定できる
シンプルにしました。
複数の自社サービス(異なるNW環境で稼働)、全て内製、という弊社の環境としては、上記で十分という感じです。
要件変われば実装変えて対応できますし^^;
やれなくてよいこと
- sudoパスワードは管理しない
- 組織構造はフラット(link_groupsは使用しない)
構成
環境概要
- インフラ構成
- AWSを使います
- STNSクライアント ->
API Gateway + Lambda + DynamoDB
DynamoDBテーブル構成
stns-osuser、stns-authorityという2テーブルで管理します。
2テーブルともにnameというカラムがプライマリキーとなります。
stns-osuser
- ユーザごとに下記の情報を1レコードとして登録します
カラム名 | 設定例 | 説明 | 必須 | 補足 |
---|---|---|---|---|
name | miyaz | ユーザ名 | ○ | 半角英数字の任意ユーザ名 |
id | 10002 | ユーザID | ○ | |
directory | /home/miyaz | ホームディレクトリ | 指定しない場合は/home/{name}となります | |
keys | ssh-rsa 〜〜,ssh-rsa 〜〜〜 | 公開鍵 | 公開鍵をカンマ区切りで指定できます | |
link_users | deploy | 公開鍵参照ユーザ | 指定したユーザの公開鍵をkeysに加えます | |
setup_commands | ["/bin/sh base_setup.sh","/bin/sh custom_setup.sh"] | stns-setup実行コマンド | stns-setupで実行したいコマンドをJSON(配列)形式で指定可能。詳細後述 | |
setup_variables | {"MAILADDRESS":"miyaz@example.com"} | stns-setup実行環境変数 | stns-setup実行時に設定するシェル変数をJSON(ハッシュ)形式で指定可能。詳細後述 |
※「値を指定しない」状態とは、レコードにそのカラムが存在しない、もしくはnullという文字列が指定された状態を指します
stns-authority
- 環境ごとにsudo可能なユーザを定義します
- 環境を識別する文字列をstnsクライアント設定(libnss_stns.conf)のBasic認証ユーザ名として指定します
- 一致するレコードがない場合はname=defaultというレコードを使用します(そのため、defaultレコードは必須)
カラム名 | 設定例 | 説明 | 必須 | 補足 |
---|---|---|---|---|
name | ec-prod | 環境を識別する文字列 | ○ | |
superusers | miyaz | sudo可能ユーザ | カンマ区切りで指定されたユーザをadmin(10001)セカンダリグループとして追加します |
※対象サーバのsudoersに、adminグループのNOPASSWORD sudo権限が付与されている前提となります(ansibleで設定してください)
※全ユーザはデフォルトでoperator(10000)グループに属します
stns-setupについて
stnsを使用してsshログインしたユーザはstns-setupというコマンドが使えるようになります。
このコマンド実行時に実際に何を実行するかをstnsバックエンドからのレスポンスで指定できます。
参考事例
stns-osuserテーブルのsetup_commandsの指定有無に関わらず、デフォルトで ~/.stns-setup.sh
を実行します。
実行時にコマンドに渡すシェル変数を、setup_varibalesで指定することができます。
例えば、setup_varibalesに{"MAILADDRESS":"miyaz@example.com"}
を指定している場合に
stns-setupコマンドで実行されるコマンドラインは下記のようになります。
env MAILADDRESS=miyaz@example.com /bin/sh /home/miyaz/.stns-setup.sh
この場合、.stns-setup.sh内でMAILADDRESS変数を使って必要な処理を行うことができます。
その他にもSlackユーザ名やGitHubユーザ名などを登録しておくといろいろ使えるかもしれません。
例えば下記のようなことに使えます。
- 開発環境のアラートメール送信先定義を書き換えてアラートメールを自分宛てにする
- Slack通知スクリプトの通知先を自分宛てのSlackユーザ名に書き換える
- GitHubユーザ名を .gitconfigに設定して、gitでごにょごにょする
セットアップ手順
以降東京リージョン指定して作業すること
DynamoDB作成
- stns-osuserテーブル作成
- プライマリキーname
- その他デフォルト設定を使用
- Auto Scaling 無効と表示されている場合はデフォルト設定を外して再作成
- stns-authorityテーブル作成
- プライマリキーname
- その他デフォルト設定を使用
- 上述のテーブル構成を参照し、必要なユーザ情報を登録しておくこと
Lambda作成
-
関数を作成
- 名前[stnsBackend]を指定
- ランタイム[Node.js 8.10]を指定
- カスタムロールとしてロール名[lambda_stnsbackend_execution]を入力
- Actionには ["dynamodb:*"] を指定
- Resourceには作成した2テーブルのARNを指定
-
コードをzipアップロード
- 事前に~/.aws/credentials設定とnodebrew等でnodejs(v8.10.0推奨)をインストールしておくこと
- コードをgit clone
-
git clone https://github.com/miyaz/stns-backend.git; cd stns-backend
- 上記リポジトリへのリンク (メインのコードはstnsBackend.jsです)
-
- 必要なnodeモジュール収集
npm install
- デプロイを実行
npm run gulp deploy
API Gateway作成
-
新しいAPIを作成
- API名[StnsBackend]
- 説明[stnsバックエンド用lambdaにproxyします]
- エンドポイントタイプ[地域]
-
リソースの作成
- プロキシリソースとして設定のチェックを入れて作成
- 統合タイプ[Lambda関数プロキシ]
- Lambdaリージョン[ap-northeast-1]
- Lambda関数[stnsBackend]
-
APIのデプロイ
- デプロイされるステージ[新しいステージ]
- ステージ名[prod]
-
APIキー作成
- 名前[stns_backend_key]
- APIキー[自動生成]
- このキーはstnsクライアント(libnss_stns.conf)に指定するので控えておくこと
-
使用量プラン作成(任意)
- 名前[stns_backend_plan]
- スロットリング レート[100] バースト[200]
- クォータは指定なし
- APIステージの追加
- API[StnsBackend] ステージ[prod]
-
カスタムドメイン用ACM発行
- ドメイン名[stns.example.com](任意)
- 検証方法[Eメールの検証]を選択
- 証明書リクエスト実施後届いたメールのリンクをクリックして承認する
-
カスタムドメイン名作成
- ドメイン名[stns.example.com]
- エンドポイントの設定[Regional]
- ACM証明書で作成済み証明書を選択
- ベースパスマッピング追加
- パス[/]
- 送信先[StnsBackend]
- ステージ[prod]
Route53設定
- example.comのホステッドゾーンを編集
- stns.example.comのCNAMEにAPI Gatewayのドメインを指定
サーバ設定
- sudoersに
%admin ALL=(ALL) NOPASSWD:ALL
を追記 - stnsを導入し、libnss_stns.confを下記のように設定
api_end_point = ["https://stns.example.com"]
# 環境を識別する名称を指定(stns-authorityテーブルname列で権限チェック)
user = "hoge-service"
password = "dummy"
ssl_verify = true
request_timeout = 3
[request_header]
x-api-key = "API GatewayのAPI認証に使用するキー"
動作確認
- stns-osuserテーブルに登録されたユーザでsshログインできること
- stns-authorityテーブルにsuperusers列に指定されたユーザでログインし、sudo lsが実行できること
おわりに
実際に運用してみて、ユーザ追加、権限昇格、削除などが一瞬で反映できるので便利です!!
一元管理することでユーザ/権限の消し忘れなども減るためセキュリティ的にも向上します。
あとは、ユーザ追加、削除などをgitで管理して、pushされたらDynamoDBに反映って
とこまで作ればもっと楽できますね。(今後やる予定)