コンテンツにスキップ

チャネル オンボーディング — システム管理者編

対象読者: automedia 開発者 (システム管理者)。メディア運営者向けの手順は メディア運営者編 を参照。

新規テナントを立ち上げる際に管理者が 1 度だけ実施する bootstrap 作業 をまとめる。bootstrap では SNS キーの初回投入も管理者が行う(鍵取得が運営者にしかできない場合は、運営者に依頼して安全な経路で受領し管理者が投入する)。完了後、運営者は メディア運営者編 に従ってチャネル運用を行い、以降のキーローテーションはセルフサービスで実施できる(LINE / Backlog / HubSpot。GitHub は _meta 横断のため管理者管理)。

0. 共通方針

認証情報の保管場所

保管先 用途
AWS Secrets Manager (/automedia/<tenant>/<provider>) runtime トークンの SoT。各 Lambda が IAM ロール経由で read
/automedia/_meta/github sync Lambda が使う GitHub Webhook secret + PAT (テナント横断)
Backlog Wiki (TTRTAGSPIN) アカウント・アプリの「在処」のみ記載。秘匿情報そのものは置かない。管理画面パスワード等の人間用ログインは Wiki が SoT

詳細は セキュリティ・シークレット を参照。

ローテーション方針

  • 既定: 90 日ごと
  • ローテーション実施は Backlog Wiki に履歴を残す
  • CloudWatch Alarm で期限通知 (Phase 1c で実装予定)

bootstrap 時点では placeholder 値を入れる

各 provider の secret は最初 placeholder 値 (_placeholder prefix) で作成しておく。Lambda 側は placeholder を検知して該当 provider 処理を no-op にする (webhook-line で実装済パターン)。本値の 初回投入は bootstrap 時に管理者put-secret-value で行う(鍵取得が運営者依存なら安全な経路で受領)。投入後のローテーションは運営者が /automedia-secret-set skill でセルフサービス実施できる(LINE / Backlog / HubSpot)。


前提要件 (AWS アカウント単位 / 初回のみ) — IdC を 2 箇所設定 (#188)

新規 AWS アカウントで automedia を立ち上げる際に アカウント全体で 1 回だけ 実施する。 テナント追加や運営者追加のたびには不要。

前提 1: "Send email OTP" を有効化 (パスワード設定経路を開通)

identitystore create-user で作成したユーザーは password 無し状態で、AWS の自動 Welcome メールが届かない。この設定を ON にすると、ユーザーが初回サインインを試みたタイミングで AWS が verification メールを自動送付し、運営者は link から初期パスワード設定を完了できる (AWS docs)。

  1. IAM Identity Center Console を開く
  2. 左メニュー Settings > Authentication タブ
  3. Standard authentication セクションの Configure をクリック
  4. Send email OTP チェックボックスを ON
  5. Save をクリック (Status が DisabledEnabled に変わることを確認)

前提 2: MFA を「サインイン時に登録するよう要求」に設定 (MFA 強制)

automedia は本番テナント secret に触れる運用なので、運営者は全員 MFA 必須とする。 パスワード設定直後に MFA 登録画面に遷移させる:

  1. Settings > Authentication タブ > Multi-factor authentication > Configure
  2. 登録された MFA デバイスをユーザーが持っていない場合: 「サインイン時に MFA デバイスを登録するよう要求する」 を選択 (デフォルトは「ユーザーをサインインを許可する」= MFA 未登録のままログイン可能)
  3. その他の設定は既定のままで OK:
  4. MFA のプロンプトをユーザーに表示: コンテキスト対応
  5. 認証タイプ: セキュリティキー / Authenticator アプリケーション
  6. MFA デバイスを管理できるユーザー: ユーザー自身も管理可
  7. 変更を保存 をクリック

API / CLI からの設定変更可否

両設定とも公開 API / CLI では設定変更も状態確認も できない (Console 専用)。 公開 API が無い理由は AWS re:Post の公式回答 を参照。

前提 1 が未有効だと /automedia-operator-onboard 自体は成功するが、運営者は SSO portal で 初期パスワード設定にたどり着けず、管理者が Console から one-time password を発行する フォールバック (§9-2) が毎回必要になる。 前提 2 を「サインインを許可する」のままにすると、運営者は MFA 未登録のままログインでき、 後で Security メニューから手動登録する形になる (セキュリティ的に非推奨)。


1. placeholder secret の作成

# LINE
aws --profile spindd-admin secretsmanager create-secret \
  --name /automedia/<tenant>/line \
  --secret-string '{
    "channel_id": "_placeholder",
    "channel_secret": "_placeholder",
    "access_token": "_placeholder"
  }' --region ap-northeast-1

# HubSpot
aws --profile spindd-admin secretsmanager create-secret \
  --name /automedia/<tenant>/hubspot \
  --secret-string '{
    "access_token": "_placeholder",
    "portal_id": "_placeholder"
  }' --region ap-northeast-1

# Backlog (space_key と webhook_secret は管理者が値を投入、api_key は placeholder)
WEBHOOK_SECRET=$(python3 -c 'import secrets; print(secrets.token_hex(32))')
aws --profile spindd-admin secretsmanager create-secret \
  --name /automedia/<tenant>/backlog \
  --secret-string "$(jq -n --arg ws "$WEBHOOK_SECRET" '{
    space_key: "spindd",
    api_key: "_placeholder",
    webhook_secret: $ws
  }')" --region ap-northeast-1

expires_at tag を付けると secret-watch Lambda (#79) が週次で期限を監視する。新規作成時に仮の期限 (例: 90 日後) を付けておく。

2. IAM Permission Set 整備

aws/tofu/iam-identity-center.tf に当該テナント用の Permission Set を追加。詳細は クレデンシャル配布: per-tenant Permission Set を参照。

resource "aws_ssoadmin_permission_set" "tenant_operator_<tenant>" {
  name             = "TenantOperator-<tenant>"
  instance_arn     = "arn:aws:sso:::instance/ssoins-18083f7232cea59f"
  session_duration = "PT8H"
}
# + inline_policy で GetSecretValue / PutSecretValue / execute-api を per-tenant ARN 限定で許可
# + 該当 SSO ユーザーへの account_assignment

tofu apply 後、運営者が aws sso login --profile spindd-<tenant> でログインできる状態になる。

3. Backlog Webhook 登録 (管理者側)

space_key / webhook_secretテナント全体で 1 度だけ設定する値 で、運営者は触らない。

# 上で生成した WEBHOOK_SECRET を URL path に埋め込む
WEBHOOK_URL="https://api.automedia.spin-dd.com/backlog/webhook/${WEBHOOK_SECRET}"

Backlog API もしくは UI で Webhook 登録:

  • URL: ${WEBHOOK_URL}
  • イベント: 課題追加 / 課題更新 / コメント追加

4. GitHub theme repo Webhook 登録

# /automedia/_meta/github の webhook_secret を取得
WEBHOOK_SECRET=$(aws --profile spindd-admin secretsmanager get-secret-value \
  --secret-id /automedia/_meta/github --query SecretString --output text \
  | jq -r .webhook_secret)

# theme repo に登録
gh api repos/spin-dd/<tenant>-hubspot-theme/hooks --method POST -F config[url]=https://api.automedia.spin-dd.com/github/webhook -F config[content_type]=application/json -F config[secret]="${WEBHOOK_SECRET}" -F events[]=push

5. tenants.json を仮値で追加

aws/tenants/_meta/tenants.json:

{
  "by_line_channel": {
    "_placeholder_<tenant>": "<tenant>"
  },
  "by_backlog_category": {
    "<category>": "<tenant>"
  },
  "by_github_repo": {
    "spin-dd/<tenant>-hubspot-theme": "<tenant>"
  }
}

LINE の channel_id は運営者が LINE Developers Console で発行後に値が確定するので、ここでは仮値で進めて後で正式値に修正する。

PR + tofu apply

6. project.json の雛形を作成

aws/tenants/<tenant>/project.json:

{
  "tenant": "<tenant>",
  "aws": {
    "profile": "spindd-<tenant>"
  },
  "channels": {
    "line": { "enabled": false },
    "hubspot": { "enabled": false }
  },
  "ai": {
    "model": "claude-opus-4-7"
  }
}

enabled: false で開始し、運営者の credential 投入完了後に true へ昇格させる (HubSpot は blog_id / author_id / author_name 取得後)。

7. welcome.json の雛形を作成

aws/tenants/<tenant>/templates/line/welcome.json:

{
  "messages": [
    {
      "type": "text",
      "text": "公式 LINE へようこそ!"
    }
  ]
}

運営者が文面を仕上げる前提で雛形のみ用意する。

8. tofu apply で確定

cd aws/tofu
tofu apply

これで Lambda / API Gateway / Schedule / Permission Set が反映される。

9. 運営者への引き継ぎ案内

全体フロー (BPMN swim lane / #188)

下図は §9 の 運営者ごと に発生するオンボーディング業務を BPMN 2.0 のスイムレーンで 表したもの。管理者・AWS (IdC + SES)・運営者の責務境界とフォールバック分岐 (verification メール不達時の OTP 発行) を 1 枚で確認できる。

運営者オンボーディング BPMN

本フローを始める前に: AWS アカウント単位の前提要件 (IdC 2 箇所設定) を 1 回だけ済ませておくこと。済んでいれば運営者追加ごとには不要。

9-1. SSO ユーザーの登録 + 招待メール送信

Identity Center 側のユーザー作成・Permission Set 割り当て・招待メール送信は管理者 skill /automedia-operator-onboard (#115 / #174 / #188) を使う。本章 §2 (IAM Permission Set 整備) で OpenTofu の account_assignment まで終わっていれば、以下 1 コマンドで完了する:

# dry-run で計画確認
node "$CLAUDE_SKILL_DIR/operator-onboard.mjs" \
  --tenant <tenant> --operator-email <user@example.com> --operator-name "<表示名>"

# 問題なければ user 作成 + 招待メール送信を 1 コマンドで
node "$CLAUDE_SKILL_DIR/operator-onboard.mjs" \
  --tenant <tenant> --operator-email <user@example.com> --operator-name "<表示名>" \
  --send-invite --apply

招待メールには次が含まれる (send-operator-invite.mjs):

  • 初期パスワード設定の手順 (SSO start URL → UserName のみ入力 → 届く verification メール 経由で password + MFA 登録)
  • ~/.aws/config snippet
  • 運営者ハンドブック URL

9-2. (フォールバック) verification メールが届かない場合: one-time password を発行

§9-0 を未設定の環境、または運営者環境のメール受信に問題があり verification メールが 届かない場合は、管理者が Console から one-time password (OTP) を発行する:

  1. IAM Identity Center Console > Users
  2. 該当運営者の UserName をクリック
  3. Reset password ボタン
  4. Generate a one-time password and share the password with the user を選択
  5. 表示された AWS access portal URL + password をコピー (画面を閉じると再表示不可)
  6. 運営者へ別経路 (Slack DM / 安全な方法) で渡す
  7. 運営者は SSO start URL に UserName + OTP でサインイン → 初期パスワード設定 + MFA 登録

OTP の有効期限は AWS 側で 7 日。期限切れの場合は同手順で再発行する。 CloudTrail に admin の ResetPassword action が記録される。

9-3. 引き継ぎ時に運営者へ共有するもの

9-3. 引き継ぎ時に運営者へ共有するもの

招待メール (§9-1) を送信していれば本文に同梱済み。別途 Slack / メールでも案内する場合は:

  • SSO start URL (例: https://<spindd-domain>.awsapps.com/start)
  • 担当テナント名 (<tenant>)
  • AWS profile 名 (spindd-<tenant>)
  • 初期パスワード設定の手順 (招待メール本文 = §9-1 で送信済み)
  • メディア運営者編 のリンク

以降は運営者がセルフサービスで進める。

10. 事後の値固定 (運営者の作業完了後)

運営者が LINE / HubSpot の credential 投入を完了したら、管理者は以下を実施:

  • LINE channel_id が確定したら tenants.jsonby_line_channel を正式値に修正して PR + tofu apply
  • HubSpot blog_id / author_id / author_name を取得し project.json > channels.hubspot に投入、enabled: truePR + tofu apply
  • E2E テスト課題で配信確認

HubSpot 値の取得:

ACCESS_TOKEN=$(aws --profile spindd-admin secretsmanager get-secret-value \
  --secret-id /automedia/<tenant>/hubspot --query SecretString --output text | jq -r .access_token)

# CMS Blog の contentGroupId
curl -H "authorization: Bearer ${ACCESS_TOKEN}" \
  https://api.hubapi.com/cms/v3/blog-settings/settings

# Blog Author の id
curl -H "authorization: Bearer ${ACCESS_TOKEN}" \
  https://api.hubapi.com/cms/v3/blogs/authors

11. 運営者引き継ぎの自動化 (将来計画)

§9 の引き継ぎ作業 (Identity Center ユーザー登録 / Permission Set assignment / SSO 情報の伝達 / 運営者編 URL の案内) は 段階的にシステム化 する。実装は別 Issue で切り出して進める。

Phase 1: welcome メッセージ生成スクリプト (#115, 実装済み)

当初は OpenTofu output 化を想定していたが、SSO アクセスポータル URL (start URL) は aws_ssoadmin_instances data source から取得できず tofu 変数のハードコードが必要になる。 代わりに 値を実行時に自動解決する生成スクリプト aws/tools/operator-welcome.mjs (依存ゼロ Node + aws CLI) で実装した。

node aws/tools/operator-welcome.mjs --tenant bato
# カスタムサブドメイン時のみ start URL を上書き:
node aws/tools/operator-welcome.mjs --tenant bato --start-url https://acme.awsapps.com/start

スクリプトは以下を自動解決し、運営者がそのまま使える welcome テキストを出力する:

  • Account ID: aws sts get-caller-identity
  • Identity Store ID: aws sso-admin list-instances (IdC home region)
  • start URL: identity store id からデフォルトポータル URL https://<identity-store-id>.awsapps.com/start を導出 (--start-url で上書き可)
  • Permission Set 名: TenantOperator-<tenant> (#112)

出力には ~/.aws/config 用 snippet ([sso-session] + [profile spindd-<tenant>]) + SSO ログイン手順 + テーマリポ初期化 (npx github:spin-dd/automedia init) + ドキュメント URL が含まれる。URL / Account ID / Role 名はすべて API から展開するため手入力ミスが起きない

出力 snippet はそのまま運営者の /automedia-aws-config-setup skill (#113) に貼り付けられる。 管理者は出力を Slack / メールで運営者に渡すだけでよい。

Phase 2.5: 招待メールの SES 自動送信 (#174, 実装済み)

AWS Identity Center にはプログラマブルな「招待メール送信 API」が無いため (CreateUser は招待メールを自動送信しない)、Phase 2 までだと管理者が Console で「Reset password」を 手動クリックする必要があった。これを SES (sesv2 send-email) での自前送信に置き換える。

新規スクリプト aws/tools/send-operator-invite.mjs および operator-onboard.mjs--send-invite オプションで送信。本文には次を含める:

  • 担当テナント / 宛先 UserName
  • 初期パスワード設定の手順 (SSO start URL → UserName 入力 → AWS から届く "Verify your email address" メール経由でパスワード設定 + MFA 登録) — #188 で修正
  • ~/.aws/config snippet (operator-welcome.mjs を再利用、HTML は <pre> で整形維持)
  • 運営者ハンドブックの URL

前提 (#188): IdC の "Send email OTP" 設定が有効化済みであること。 Console > Settings > Authentication > Standard authentication > Configure > Send email OTP を ON。API/CLI で作成したユーザーは password 無し状態のため、この 設定を有効化していないと初回サインイン時に verification メールが届かず、ユーザーは 初期パスワード設定にたどり着けない (「Forgot password?」は既存ユーザー再設定用で MFA 検証を要求するため、新規 API ユーザーは進めない)。未設定環境では、管理者が Users > 該当ユーザー > Reset password > Generate a one-time password で OTP を 発行して運営者へ別経路で渡すフォールバックが必要。 参照: https://docs.aws.amazon.com/singlesignon/latest/userguide/userswithoutpwd.html

# 単独実行 (dry-run でプレビュー)
node aws/tools/send-operator-invite.mjs \
  --tenant bato --operator-email hanako@example.com --operator-name "花子"
# ↑ --from 既定 = noreply@automedia.spin-dd.com

# operator-onboard と同時実行 (user 作成と招待メール送信を 1 コマンドで)
node "$CLAUDE_SKILL_DIR/operator-onboard.mjs" \
  --tenant bato --operator-email hanako@example.com --operator-name "花子" \
  --send-invite --apply

前提 (Tofu で自動セットアップ済 / #174):

  • automedia.spin-dd.com zone が Route 53 に存在し、親 spin-dd.com から NS 委譲済
  • SES Domain identity automedia.spin-dd.com が verified、Easy DKIM 有効
  • Custom MAIL FROM = mail.automedia.spin-dd.com (SPF alignment 用 MX/TXT)
  • DMARC TXT (_dmarc.automedia.spin-dd.com) が p=none で監視中
  • → SPF / DKIM / DMARC のすべてが pass し、Gmail / Outlook 等で迷惑メール判定されにくい

SES が sandbox モード (ProductionAccessEnabled=false) の場合は宛先側も verified が必要。 本番運用化は AWS Console > SES > Account dashboard で production access を申請する。 呼び出し元 IAM に ses:SendEmail (sesv2) の許可が必要。

Phase 2: 管理者 skill /automedia-operator-onboard (#115, 実装済み)

管理者が 1 コマンドで運営者追加 を完結できる管理者専用 skill (.claude/skills/automedia-operator-onboard、依存ゼロ Node + aws CLI)。

# まず dry-run (既定): 計画 (user/assignment の create/exists) + welcome を確認
node "$CLAUDE_SKILL_DIR/operator-onboard.mjs" \
  --tenant bato --operator-email hanako@example.com --operator-name "花子"

# 問題なければ --apply で実行
node "$CLAUDE_SKILL_DIR/operator-onboard.mjs" \
  --tenant bato --operator-email hanako@example.com --operator-name "花子" --apply

挙動 (冪等): - Identity Store にユーザーが居なければ CreateUser、居れば再利用 - TenantOperator-<tenant> Permission Set に CreateAccountAssignment (割当済みは skip) - operator-welcome.mjs (Phase 1) で welcome 生成、--notify slack で Slack 投稿 (任意) - CreateUser / CreateAccountAssignment は CloudTrail に記録 (監査)

設計上の要点:

項目 内容
実行モデル 既定 dry-run、--apply で実 API。ID 作成の誤実行を防ぐ
権限 呼び出し元 (管理者の SSO 認証) を使用。必要 action は SKILL.md / 下記に明記。AdministratorAccess 相当ならそのまま満たす (tofu でのロール新設はしない)
配布 管理者専用のため SKILL.md に distribute: falsenpx ... init/upgrade の配布対象から除外される (テーマリポへは配らない)
Slack --notify slack + SLACK_WEBHOOK_URL env (未設定なら skip)

必要 IAM action (管理者の認証情報側): sso-admin:ListInstances / ListPermissionSets / DescribePermissionSet / ListAccountAssignments / CreateAccountAssignment / DescribeAccountAssignmentCreationStatusidentitystore:GetUserId / CreateUsersts:GetCallerIdentity

Phase 3 以降の発展案 (参考)

  • Backlog Wiki に運営者向けオンボーディング page を自動生成 (spindd.backlog.com/wiki/TTRTAGSPIN/Operators/<tenant>)
  • テナント PR マージで GitHub Actions が起動して tofu apply + 通知まで一気通貫
  • SES でメール直接送信 (運営者のメールアドレスが既知の前提)

これらは Phase 1c / Phase 4 (マルチテナント Bootstrap 自動化、ロードマップ) のスコープに含める。

管理者チェックリスト

AWS アカウント単位 (初回のみ / 1 回だけ)

  • IdC Console > Settings > Authentication > Standard authentication で Send email OTP を有効化 (前提 1)
  • IdC Console > Settings > Authentication > Multi-factor authentication で「サインイン時に MFA デバイスを登録するよう要求する」を選択 (前提 2)

テナント追加ごと (1 テナント = 1 回)

scaffold 部分(tenants.json / project.json / welcome template / var.tenants)は node aws/tools/bootstrap-tenant.mjs --tenant <t> [--backlog-category <名>] --apply でまとめて生成できる(#84、冪等)。残りの手作業は以下。

  • /automedia/<tenant>/line / hubspot / backlog を placeholder で create-secret
  • aws/tofu/iam-identity-center.tfTenantOperator-<tenant> Permission Set 追加 + 運営者を assignment
  • Backlog の space_key / webhook_secret を投入、Webhook 登録 (register-saas.mjs --saas backlog --project-key <KEY> --apply)
  • GitHub theme repo の Webhook 登録 (GITHUB_PAT=... register-saas.mjs --saas github --apply)
  • LINE webhook endpoint 登録 (register-saas.mjs --saas line --apply) / HubSpot Private App 作成 (register-saas.mjs --saas hubspot で手順表示)
  • aws/tenants/_meta/tenants.jsonby_line_channel (仮値) / by_backlog_category / by_github_repo を追加して PR
  • aws/tenants/<tenant>/project.json 雛形を作成 (enabled: false で開始)
  • aws/tenants/<tenant>/templates/line/welcome.json 雛形を作成
  • tofu apply

運営者追加ごと (1 運営者 = 1 回)

  • /automedia-operator-onboard --send-invite --apply で運営者を Identity Store に作成 + 招待メール送信 (§9-1)
  • 運営者へ SSO 情報 + メディア運営者編 のリンクを案内 (招待メールに同梱済)
  • (運営者作業完了後) tenants.json の LINE channel_id 正式値修正
  • (運営者作業完了後) project.json > channels.hubspotblog_id / author_id / author_name 投入 + enabled: true
  • E2E テスト課題で配信確認

関連