メインコンテンツに移動

業務の再設計からはじめる Account Factory for Terraform による AWS アカウント払い出しの半自動化

2026-11-04 | Author : 今泉 和馬 (弥生株式会社)

Missing alt text value

はじめに

AWS マルチアカウント環境では、新規 AWS アカウントの払い出しがボトルネックになりがちです。 依頼・承認・作成・完了連絡が分散すると、リードタイムは伸び、作業は属人化します。

AWS Control Tower Account Factory for Terraform (AFT) を使えば、AWS アカウント作成を GitOps のパイプラインに乗せられます。

しかしツール導入だけでは業務はなくなりません。承認プロセスや例外対応、自動化の範囲も含めて設計として決めておかないと、チャットとコンソールによる手作業に逆戻りするリスクが残ります。

この記事では、アカウント払い出しの業務をどう切り分け、どこを自動化し、どこを人による判断として残したかを中心に説明します。
あわせて、依頼チケットからアカウントリクエスト (account-request) の PR を作成する実装と、導入後の変化もお伝えします。

X ポスト » | Facebook シェア » | はてブ »

builders.flash メールメンバー登録

builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。

今すぐ登録 »

背景

弊社では AWS Organizations で約 270 アカウントを管理しており、新規払い出しは月 5 件程度です。アカウント払い出しの半自動化は以前から課題となっていましたが、限られた担当者で運用するなか、次の 2 つを同時に進めるのが難しく着手が後回しになっていました。

  1. AFT 本体の導入 : AWS Control Tower 連携、GitOps、パイプライン
  2. 業務設計の棚卸し : 依頼〜承認〜例外、自動化と手動の境界

後者はツール導入だけでは解決できません。
今回は生成 AI を仕様・フロー図・Runbook の下書きに使い、人がスコープの境界と、どこに承認ステップを置くかを判断する、という分担にしました。

その結果、依頼管理基盤 (本稿では Notion) での起票から、チャットツール (本稿では Slack) での承認、アカウントリクエストの PR 作成、結果の同期、台帳の管理までをつないだ半自動化を、約 2 か月で実装・検証まで進められました。

当時どんな課題があったのか

ボトルネックはコンソールからのアカウント作成、AWS CloudFormation StackSets の手動実行、アカウント管理台帳への転記でした。

弊社では、アカウントを作成する前に、その作成が妥当かを確認しています。妥当性判断、アカウント作成・削除の依頼が各種ツールに散らばっていて全体の状況を把握しにくい状態でした。

また AWS Control Tower コンソールでの作成自体にも十数分〜数十分の待ち時間があり、運用者は作成状況の監視や確認が必要でした。

導入前 (As-Is) の業務フロー

メーリングリスト作成は、もともと関連プロセスとして別に管理しています。 「妥当性判断 → メーリングリスト作成 → アカウント作成」とすると待ち時間が入りうるため、妥当性の可否判断やメーリングリスト作成待ちをアカウント作成パイプラインに含めない設計が必要でした。

なぜ業務設計からやり直したのか

AFT の価値は「手作業全部を消す」ことではなく、どこをコードやパイプラインの責務にするかを合意することだと考えました。   また依頼管理基盤の刷新に合わせて、業務設計をやり直しています。  To-Be では、依頼窓口を依頼管理基盤に一本化したうえで、妥当性判断とアカウント作成を別チケットに分けました。

導入後 (To-Be) の業務フロー

業務フローの設計方針

Phase A は承認と連絡までで完了し、AFT のパイプラインは Phase B のチケットでのみ動きます。自動化するのは PR 作成、AFT 払い出し、チケットへの結果反映、台帳更新です。人が担うのは、妥当性と実行の承認、PR レビューです。

スモールスタートのため、メーリングリスト作成や一部の監査・事後チェックは対象外としました。対象外にしたことで生じるリスクは、許容した理由とあわせて Runbook に明記しています。As-Is で手動実行していた StackSets は、StackSets の自動デプロイ (AutoDeployment) に任せています。

依頼管理基盤では、依頼内容と進捗状況を一元管理します。チャットツールは、承認依頼と通知の窓口です。

AWS 側では、依頼の取り込みと条件の判定、PR の作成、AFT による払い出し、結果のチケットへの反映までを行います。

実行前には承認の記録を確認します。ステータスは「レビュー完了」と「自動実行開始」用のプロパティでフェーズを分けています。

チケットの検知は、現時点では Amazon EventBridge Scheduler による定期ポーリングで行っています。

図に、依頼受付から結果の同期までの流れを示します。結果の同期は、アカウントごとの customizations パイプラインの完了を EventBridge で検知し、チケットへ反映します。 

AFT 半自動化の全体構成

依頼チケットからアカウントリクエストの PR を作成

AFT では、アカウントリクエストを aft-account-request リポジトリで管理します。このリポジトリに Terraform ファイルがマージされると、パイプラインが起動します。今回の仕組みの中心は、チケットの値から Terraform ファイルを生成し、AWS CodeCommit 上で PR を作成することです。

  1. EventBridge Scheduler で定期的に起動する Lambda 関数が、「適用中」などの条件を満たすチケットを検出し、Amazon SQS の FIFO キューに投入する
  2. PR 作成用の Lambda 関数がキューのメッセージから Terraform ファイル(.tf)を生成する
  3. 作業ブランチへコミットし、create_pull_request で PR を作成する
  4. チャットツール上で PR の承認を依頼し、承認されると自動でマージされて AFT の払い出しパイプラインが起動する

同じブランチに未マージの PR があれば、新しく作成せずにその PR を返し、二重作成を防いでいます。また PR 作成前段では FIFO キューで依頼を直列化し、PR 作成や承認依頼の競合を防いでいます。

PR レビューでは主に、アカウントの配置先 OU が意図どおりか、ルートユーザーとなるメールアドレスが既に使われていないかを確認します。

チケットの値から、AFT の公式モジュールを呼び出す Terraform コードを生成します (値は一般化しています)。

チケットから AFT アカウントリクエスト用 Terraform を生成

python
def generate_account_request_tf(account: dict) -> str:
    """依頼チケットの値から aft-account-request 用の .tf を生成する。"""
    name = account["account_name"]
    return f'''
module "aft_account_request_{name}" {{
  source = "./modules/aft-account-request"

  control_tower_parameters = {{
    AccountEmail              = "{account["account_email"]}"
    AccountName               = "{name}"
    ManagedOrganizationalUnit = "{account["ou"]}"
    SSOUserEmail              = "{account["sso_email"]}"
    SSOUserFirstName          = "AFT"
    SSOUserLastName           = "Admin"
  }}

  change_management_parameters = {{
    change_requested_by = "request automation"
    change_reason       = "Automated request from ticket {account["request_id"]}"
  }}

  account_tags = {{
    Environment = "{account.get("environment", "Production")}"
    ManagedBy   = "AFT"
  }}
}}
'''

生成結果のイメージ

bash
#terraform
module "aft_account_request_example_workload_01" {
  source = "./modules/aft-account-request"

  control_tower_parameters = {
    AccountEmail              = "ops+example-01@example.com"
    AccountName               = "example_workload_01"
    ManagedOrganizationalUnit = "Workloads"
    SSOUserEmail              = "ops+example-01@example.com"
    SSOUserFirstName          = "AFT"
    SSOUserLastName           = "Admin"
  }

  change_management_parameters = {
    change_requested_by = "request automation"
    change_reason       = "Automated request from ticket REQ-123"
  }

  account_tags = {
    Environment = "Production"
    ManagedBy   = "AFT"
  }
}

ブランチ作成・ファイルのコミット・PR 作成の骨子

PR 本文とチャット通知に AccountName・OU・メールを載せ、差分を追いやすくしています。 連携に障害が起きた場合は、同じ Terraform ファイルを手動でコミットし、通常と同じレビューを経て適用する手順も用意しています。

python
def create_account_request_pr(codecommit, *, repo: str, default_branch: str, account: dict):
    """Terraform 定義をコミットし、aft-account-request リポジトリへ PR を開く。"""
    branch = f"aft/{account['request_id']}"
    path = f"terraform/{account['account_name']}.tf"

    existing = find_open_pull_request(codecommit, repo, branch)
    if existing:
        return existing["pullRequestId"]

    base = get_branch_tip(codecommit, repo, default_branch)
    ensure_branch(codecommit, repo, branch, base)
    put_file(
        codecommit,
        repo=repo,
        branch=branch,
        path=path,
        content=generate_account_request_tf(account),
        message=f"feat(aft): account request for {account['account_name']}",
    )

    pr = codecommit.create_pull_request(
        title=f"[AFT] {account['account_name']}",
        description=build_pr_description(account),  # OU / メールを明示
        targets=[{
            "repositoryName": repo,
            "sourceReference": branch,
            "destinationReference": default_branch,
        }],
    )
    return pr["pullRequest"]["pullRequestId"]

導入時に工夫した点

例外対応では、差し戻された依頼も、再度承認を経てから自動実行するようにしています。 複数の依頼を処理する際に一部が失敗しても、ほかの依頼は止めずに処理を続け、成功した分をまとめて次の工程に進めます。削除処理では、タイムアウトと恒久的なエラーを区別し、エラーを見落とさないようにしています。

依頼の取り込み処理は、複数の条件 (例: 自動実行のステータス、依頼種別がアカウント作成であること、自動化対象のフラグ) をすべて満たすときだけ動きます。

ステータスを手動で「適用中」にしても、承認の記録がなければスキップするなど、承認を経ずに実行されることを防ぐチェックも入れています。

導入によって実現できたこと

約 2 か月の半自動化で、次の流れを実現できました。

  1. 依頼者が依頼管理基盤のフォームで起票する
  2. 妥当性判断チケットで作成の可否を判断する
  3. メーリングリスト準備後、作成チケットで実行承認する
  4. 依頼を検証し、アカウントリクエストの PR を自動作成する
  5. PR を確認・承認し、AFT のパイプラインでアカウントを払い出す
  6. 結果をチケットへ反映し、台帳を更新する

人がコンソールでアカウントを作成していた運用を見直し、人が担う作業を承認と例外対応に絞り込めました。
導入前は転記やコンソール操作に 1 時間以上かかることもありましたが、導入後の実作業時間は 5 分以内で、承認操作のあとは作成完了を待つだけでよくなりました。

読者の方には、まず次を試していただけるとよいと考えています。

  1. As-Is の業務フローを、「誰が」「何を待っているか」がわかる形で整理する
  2. 各ステップを「自動化する」「あえて手動で残す」「対象外にする」のいずれかに分類する
  3. 手動で残す確認ポイントには、残す理由を書き添える
  4. 完了条件を、アカウントリクエスト用パイプラインの成功と、customizations まで終えた運用上の作業完了の 2 段階で定義する
  5. 差し戻しや障害発生時を想定した対応手順を Runbook として定める

まとめ

AFT の価値は、アカウント作成を Terraform で行えること以上に、アカウント運用の手順と承認の流れがコードと記録として残り、後から検証できるようになることだと考えています。少人数でも、業務設計の棚卸しと自動化の境界を先に決め、そのうえで AFT をつなぐと半自動化を進めやすくなります。

自動化の範囲を一度に広げず、承認など人が担う部分を先に決めておくこと、そして差し戻しや障害などの例外対応の手順を事前に用意しておくことで、半自動化した仕組みを本番環境でも安心して運用できます。

筆者プロフィール

今泉 和馬 (Kazuma Imaizumi)
Engineer, Platform Engineering Department, Yayoi Co., Ltd.

Yayoi Co., Ltd. にて、AWS を中心としたクラウド基盤・マルチアカウント運用に従事。AWS Control Tower および Account Factory for Terraform (AFT) によるアカウント払い出しの半自動化や、SIEM on Amazon OpenSearch Service を用いたログ分析・セキュリティ監視に取り組む。好きな AWS サービスは AWS Step Functions です。
 

Missing alt text value