今月 GA された AWS DevOps Agent のスペース作成から GitHub 連携までを AWS CDK で実装してみた

今月 GA された AWS DevOps Agent のスペース作成から GitHub 連携までを AWS CDK で実装してみた

2026.04.18





こんにちは、製造ビジネステクノロジー部の若槻です。

AWS 環境上でのトラブルシュートと解決を自律的に行うための AI サービスである AWS DevOps Agent がついに今月に GA され、東京を含む6リージョンで一般利用可能になりました。プレビュー段階から既にその威力を体験されていた方も多いのではないでしょうか。

https://aws.amazon.com/jp/blogs/news/announcing-general-availability-of-aws-devops-agent/

今回は、AWS DevOps Agent のスペース作成から GitHub 連携までを AWS CDK で実装してみました。

実装した構成

今回実装した主なリソースは以下です。

リソース 役割
Agent Space DevOps Agent の論理コンテナ
Agent Space Role Agent Space に割り当てる IAM ロール
Operator Role オペレーター画面からスペースを操作するための IAM ロール
AWS Association AWS アカウントとの関連付け
GitHub Association GitHub リポジトリとの関連付け

construct は責務ごとに lib/constructs/devops-agent/ 配下に分割しました。

lib/constructs/devops-agent/
├── agent-space-role/
├── operator-role/
├── aws-association/
├── github-association/
└── index.ts

やってみた

前提

GA により東京リージョン(ap-northeast-1)でも利用可能になったので、今回は東京リージョンで実装します。

aws-cdk-lib/aws-devopsagentv2.232.0(2025年12月5日リリース)で追加されました。それ以前のバージョンでは利用できないため、2.232.0 未満の場合は以下で更新します。

npm install aws-cdk-lib@latest aws-cdk@latest constructs@latest

0. GitHub service の事前登録(マネジメントコンソール)

GitHub Association を CDK で作成するには、事前にマネジメントコンソールから GitHub service を登録しておく必要があります。GitHub は CLI(CloudFormation)による Capability 登録に対応していないため、この手順だけは手動で実施します。

AWS DevOps Agent コンソールの Capability Providers → Registration → Pipeline → GitHub から GitHub service を登録します。


Capability Providers → Register capabilities → Pipeline → GitHub

Register ボタンをクリックすると GitHub Account / Organization の登録画面に遷移します。


Register GitHub Account / Organization

Submit をクリックすると GitHub に遷移し、AWS DevOps Agent GitHub App のインストール先を選択します。なお、App 名は AWS DevOps Agent (us-east-1) と表示されますが、サービス追加先のリージョンに関わらず us-east-1 と付きます。


GitHub App のインストール先を選択する

これで GitHub App がインストールされました。


インストールされた GitHub App

マネジメントコンソールに戻ると、Capability Providers の Currently registered に GitHub が表示されます。また、Agent Space 側で GitHub Association を作成すると、画像のように Agent Space との紐付けが確認できます(本手順では後続で作成しますが、作成後のキャプチャのため既に紐付けが行われています)。


Capability Providers → Registration → Currently registered に GitHub が表示される

登録後、以下のコマンドで serviceId(UUID)を取得できます。

aws devops-agent list-services
# {
#     "services": [
#         {
#             "serviceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", # ←これ
#             "serviceType": "github",
#             "additionalServiceDetails": {
#                 "github": {
#                     "owner": "your-owner",
#                     "ownerType": "user"
#                 }
#             }
#         }
#     ]
# }

1. construct の設計

ここからは CDK による実装です。DevOpsAgentConstruct を親として、各リソースを sub construct に分割しました。

lib/constructs/devops-agent/index.ts
import * as devopsagent from "aws-cdk-lib/aws-devopsagent";
import { Construct } from "constructs";

import { commonParameter } from "../../../bin/parameter";
import { AgentSpaceRoleConstruct } from "./agent-space-role";
import { AwsAssociationConstruct } from "./aws-association";
import {
  GitHubAssociationConstruct,
  GitHubAssociationProps,
} from "./github-association";
import { OperatorRoleConstruct } from "./operator-role";

interface DevOpsAgentConstructProps {
  githubAssociations: GitHubAssociationProps;
}

/**
 * DevOps Agent リソース実装
 * @see https://github.com/aws-samples/sample-aws-devops-agent-cdk/blob/main/lib/devops-agent-stack.ts
 */
export class DevOpsAgentConstruct extends Construct {
  constructor(scope: Construct, id: string, props: DevOpsAgentConstructProps) {
    super(scope, id);

    const { githubAssociations } = props;
    const { projectNamePascalCase } = commonParameter;

    /**
     * Operator 用ロールと Agent Space 用監視ロールの作成
     */
    const agentSpaceRole = new AgentSpaceRoleConstruct(this, "AgentSpaceRole");
    const operatorRole = new OperatorRoleConstruct(this, "OperatorRole");

    const agentSpace = new devopsagent.CfnAgentSpace(this, "AgentSpace", {
      name: `${projectNamePascalCase}AgentSpace`,
      operatorApp: {
        iam: {
          operatorAppRoleArn: operatorRole.role.roleArn,
        },
      },
    });

    /**
     * Agent Space と AWS リソースの関連付け
     */
    const awsAssociation = new AwsAssociationConstruct(this, "Association", {
      agentSpace,
      agentSpaceRole: agentSpaceRole.role,
    });
    awsAssociation.association.addDependency(agentSpace);

    /**
     * Agent Space と GitHub リポジトリの関連付け
     */
    const gitHubAssociation = new GitHubAssociationConstruct(
      this,
      "GitHubAssociation",
      {
        agentSpace,
        githubAssociations,
      },
    );
    gitHubAssociation.association.addDependency(agentSpace);
  }
}

2. Agent Space Role

Agent Space に割り当てる監視ロールです。AWS マネージドポリシー AIDevOpsAgentAccessPolicy をアタッチして、AWS リソースの読み取り権限を付与します。また、Resource Explorer のサービスリンクロール作成権限をインラインポリシーで付与します。

lib/constructs/devops-agent/agent-space-role/index.ts
import * as cdk from "aws-cdk-lib";
import * as iam from "aws-cdk-lib/aws-iam";
import { Construct } from "constructs";

/**
 * Agent Space 用の監視ロール実装
 * @see https://github.com/aws-samples/sample-aws-devops-agent-cdk/blob/main/lib/devops-agent-stack.ts
 * @see https://docs.aws.amazon.com/ja_jp/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-migrating-from-public-preview-to-general-availability.html#step-1-update-monitoring-roles
 */
export class AgentSpaceRoleConstruct extends Construct {
  public readonly role: iam.Role;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    const stack = cdk.Stack.of(this);

    this.role = new iam.Role(this, "Default", {
      assumedBy: new iam.ServicePrincipal("aidevops.amazonaws.com", {
        conditions: {
          StringEquals: {
            "aws:SourceAccount": stack.account,
          },
          ArnLike: {
            "aws:SourceArn": stack.formatArn({
              service: "aidevops",
              resource: "agentspace",
              resourceName: "*", // 循環参照回避のためワイルドカードで指定
            }),
          },
        },
      }),
      managedPolicies: [
        /**
         * Agent Space 用のアクセス許可を付与するマネージドポリシーをアタッチ
         * @see https://docs.aws.amazon.com/ja_jp/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-migrating-from-public-preview-to-general-availability.html#new-managed-policies
         */
        iam.ManagedPolicy.fromAwsManagedPolicyName("AIDevOpsAgentAccessPolicy"),
      ],
      inlinePolicies: {
        AllowCreateServiceLinkedRoles: new iam.PolicyDocument({
          statements: [
            /**
             * 以下を参考にサービスリンクロール作成権限を追加
             * @see https://docs.aws.amazon.com/ja_jp/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-migrating-from-public-preview-to-general-availability.html#step-1-update-monitoring-roles
             */
            new iam.PolicyStatement({
              actions: ["iam:CreateServiceLinkedRole"],
              resources: [
                stack.formatArn({
                  service: "iam",
                  region: "",
                  resource: "role",
                  resourceName:
                    "aws-service-role/resource-explorer-2.amazonaws.com/AWSServiceRoleForResourceExplorer",
                }),
              ],
            }),
          ],
        }),
      },
    });
  }
}

Resource Explorer は DevOps Agent がトポロジーを探索するために使用されます。トポロジーとは AWS リソース間の依存・接続関係のグラフ構造で、DevOps Agent はこれをもとに問題の影響範囲や根本原因を自律的に分析します。

https://docs.aws.amazon.com/devopsagent/latest/userguide/about-aws-devops-agent-what-is-a-devops-agent-topology.html

トポロジーは DevOps Agent のオペレーター画面でも下記のように確認可能です。


DevOps Agent オペレーター画面のトポロジービュー

なお、Agent Space Role はマネジメントコンソールの Agent Spaces → Capabilities → Cloud の各ソースから確認可能です。


Agent Spaces → Capabilities → Cloud → AWS Association


Edit primary cloud source

3. Operator Role

オペレーター画面から Agent Space を操作するためのロールです。AWS マネージドポリシー AIDevOpsOperatorAppAccessPolicy をアタッチし、assumeRolePolicy.addStatementssts:TagSession を追加します。このポリシーは aws:PrincipalTag/AgentSpaceId を前提としており、sts:TagSession がないとオペレーター画面から Agent Space を開いても aidevops:GetAgentSpace が denied になります。

lib/constructs/devops-agent/operator-role/index.ts
import * as cdk from "aws-cdk-lib";
import * as iam from "aws-cdk-lib/aws-iam";
import { Construct } from "constructs";

/**
 * オペレーター用ロール実装
 * @see https://github.com/aws-samples/sample-aws-devops-agent-cdk/blob/main/lib/devops-agent-stack.ts
 */
export class OperatorRoleConstruct extends Construct {
  public readonly role: iam.Role;

  constructor(scope: Construct, id: string) {
    super(scope, id);

    const stack = cdk.Stack.of(this);
    const accountId = stack.account;

    /**
     * AIDevOps サービスプリンシパルの許可条件
     */
    const principalConditions = {
      StringEquals: {
        "aws:SourceAccount": accountId,
      },
      ArnLike: {
        "aws:SourceArn": stack.formatArn({
          service: "aidevops",
          resource: "agentspace",
          resourceName: "*", // 循環参照回避のためワイルドカードで指定
        }),
      },
    };

    const servicePrincipal = new iam.ServicePrincipal(
      "aidevops.amazonaws.com",
      { conditions: principalConditions },
    );

    this.role = new iam.Role(this, "Default", {
      assumedBy: servicePrincipal,
      managedPolicies: [
        /**
         * オペレーターアプリ用のアクセス許可を付与するマネージドポリシーをアタッチ
         * @see https://docs.aws.amazon.com/ja_jp/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-migrating-from-public-preview-to-general-availability.html#new-managed-policies
         */
        iam.ManagedPolicy.fromAwsManagedPolicyName(
          "AIDevOpsOperatorAppAccessPolicy",
        ),
      ],
    });

    /**
     * sts:TagSession を許可するステートメントを追加
     * @see https://docs.aws.amazon.com/ja_jp/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-migrating-from-public-preview-to-general-availability.html#step-2-update-the-operator-role-iam
     */
    this.role.assumeRolePolicy?.addStatements(
      new iam.PolicyStatement({
        actions: ["sts:TagSession"],
        principals: [servicePrincipal],
        conditions: principalConditions,
      }),
    );
  }
}

なお、Operator Role はマネジメントコンソールの Agent Spaces → Access → Operator access から確認可能です。


Agent Spaces → Access → Operator access

4. AWS Association

AWS アカウントとの関連付けです。Agent Space が監視対象とするアカウントを、作成先自身のアカウントであっても、明示的に指定する必要があります。serviceId: "aws" を指定し、configuration.aws に Agent Space Role の ARN とアカウント ID を渡します。

lib/constructs/devops-agent/aws-association/index.ts
import { Stack } from "aws-cdk-lib";
import * as devopsagent from "aws-cdk-lib/aws-devopsagent";
import * as iam from "aws-cdk-lib/aws-iam";
import { Construct } from "constructs";

interface AwsAssociationConstructProps {
  agentSpace: devopsagent.CfnAgentSpace;
  agentSpaceRole: iam.IRole;
}

/**
 * DevOps Agent と AWS リソースの関連付け実装
 */
export class AwsAssociationConstruct extends Construct {
  public readonly association: devopsagent.CfnAssociation;

  constructor(
    scope: Construct,
    id: string,
    props: AwsAssociationConstructProps,
  ) {
    super(scope, id);
    const accountId = Stack.of(this).account;

    this.association = new devopsagent.CfnAssociation(this, "Default", {
      agentSpaceId: props.agentSpace.ref,
      serviceId: "aws",
      configuration: {
        aws: {
          assumableRoleArn: props.agentSpaceRole.roleArn,
          accountId,
          // 関連付け対象に応じて monitor / source を指定する。
          // このスタックでは DevOps Agent に監視させる対象 AWS アカウント自身を
          // 関連付けているため、monitor を指定する。
          accountType: "monitor",
        },
      },
    });
  }
}

なお、accountType: "monitor" とすることでマネジメントコンソール上の Primary source として登録されます。Agent Spaces → Capabilities → Cloud → Primary source から確認可能です。


Agent Spaces → Capabilities → Cloud → Primary source

5. GitHub Association

セクション 0 で登録した GitHub service を使って、GitHub リポジトリとの関連付けを作成します。serviceId(AWS 側の UUID)と repoId(GitHub の数値 ID)を以下のコマンドで確認します。

# serviceId の確認
aws devops-agent list-services
# {
#     "services": [
#         {
#             "serviceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", # ←これ
#             "serviceType": "github",
#             "additionalServiceDetails": {
#                 "github": {
#                     "owner": "your-owner",
#                     "ownerType": "user"
#                 }
#             }
#         }
#     ]
# }

# repoId(9桁の数値 ID)の確認
gh api repos/<owner>/<repo> --jq .id

取得した値を bin/parameter.ts に設定します。値の渡し方は環境に合わせて適宜変更してください。

bin/parameter.ts
devOpsAgent: {
  githubAssociations: {
    serviceId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // `aws devops-agent list-services` で確認した UUID
    owner: "your-org",
    ownerType: "organization or user",
    repoName: "your-repo",
    repoId: "123456789", // `gh api repos/<owner>/<repoName> --jq .id` で確認した数値 ID
  },
},
lib/constructs/devops-agent/github-association/index.ts
import * as devopsagent from "aws-cdk-lib/aws-devopsagent";
import { Construct } from "constructs";

export interface GitHubAssociationProps
  extends devopsagent.CfnAssociation.GitHubConfigurationProperty {
  serviceId: string;
}

interface GitHubAssociationConstructProps {
  agentSpace: devopsagent.CfnAgentSpace;
  githubAssociations: GitHubAssociationProps;
}

/**
 * DevOps Agent と GitHub の関連付け実装
 */
export class GitHubAssociationConstruct extends Construct {
  public readonly association: devopsagent.CfnAssociation;

  constructor(
    scope: Construct,
    id: string,
    props: GitHubAssociationConstructProps,
  ) {
    super(scope, id);

    const { agentSpace, githubAssociations } = props;
    const { serviceId, owner, ownerType, repoId, repoName } =
      githubAssociations;

    this.association = new devopsagent.CfnAssociation(this, "Default", {
      agentSpaceId: agentSpace.ref,
      serviceId,
      configuration: {
        gitHub: {
          ownerType,
          owner,
          repoId,
          repoName,
        },
      },
    });
  }
}

作成された GitHub Association はマネジメントコンソールの Agent Spaces → Capabilities → Pipeline から確認可能です。


Agent Spaces → Capabilities → Pipeline に GitHub リポジトリが表示される

動作確認

CDK デプロイ後、以下を確認します。

Agent Space の作成: マネジメントコンソールの Agent Spaces に Agent Space が表示されます。


Agent Spaces に Agent Space が作成された

AWS Association: Agent Spaces → Capabilities → Cloud → Primary source のステータスが Valid になっています(確認画面は 4. AWS Association を参照)。

GitHub Association: Agent Spaces → Capabilities → Pipeline に対象リポジトリが表示されています(確認画面は 5. GitHub Association を参照)。

Operator アクセス: Agent Spaces → Access → Operator access の Web app link からオペレーター画面を開けます(確認画面は 3. Operator Role を参照)。


Agent Space の詳細画面。トポロジーマッピングが完了し Operator access からオペレーター画面を開ける

オペレーター画面です。この画面からチャット形式で DevOps Agent に問い合わせができます。


DevOps Agent オペレーター画面

試しにヘルスサマリーを問い合わせてみると、過去24時間の AWS リソース状況をまとめて回答してくれます。


過去24時間のヘルスサマリーを問い合わせた結果

GitHub 連携が有効なため、「GitHub リポジトリの README と実際のインフラに乖離はないか」といった問い合わせも可能です。


GitHub リポジトリの README と実際のインフラの乖離を問い合わせた結果

注意点

パブリックプレビュー時の実装から移行が必要

パブリックプレビュー時の実装は、一般提供開始後の権限モデルに合わせた移行が必要です。

https://docs.aws.amazon.com/devopsagent/latest/userguide/configuring-capabilities-for-aws-devops-agent-migrating-from-public-preview-to-general-availability.html

本記事の実装では既に移行済みの構成となっています。既存のパブリックプレビュー実装がある場合は上記ドキュメントを参考に移行してください。

なお、公式サンプルの CDK 実装も先週新しい権限モデルへの移行が行われたようです。

https://github.com/aws-samples/sample-aws-devops-agent-cdk

Agent Space と IAM ロールの循環依存

Agent Space には operatorAppRoleArn が必要で、一方 IAM ロール側の trust policy で ArnEquals を使って特定の Agent Space ARN に絞ろうとすると循環依存になります。(実行ロールの権限組み立てで良くあるやつですね。)

AgentSpace → operatorRole.roleArn(を参照)
operatorRole → agentSpace.attrArn(を参照)← 循環!

Agent Space Role(監視ロール)でも同様です。今回は ArnLikeresourceName にワイルドカード(*)を指定して回避しました。

ArnLike: {
  "aws:SourceArn": stack.formatArn({
    service: "aidevops",
    resource: "agentspace",
    resourceName: "*", // 循環参照回避のためワイルドカードで指定
  }),
},

serviceIdrepoId の混同

パラメータ 意味 確認方法
serviceId AWS 側に登録された GitHub service の UUID aws devops-agent list-services
repoId GitHub リポジトリの数値 ID gh api repos/<owner>/<repo> --jq .id

なお serviceId: "github" のような文字列は無効です。筆者も最初ここを勘違いして詰まりました。

おわりに

AWS DevOps Agent のスペース作成から GitHub 連携までを AWS CDK で実装しました。

GA されたら CDK 化したいと思っていたので、東京リージョンでの利用と合わせて早速実装できてよかったです。L1 construct でも十分にリソースを作成でき、責務ごとに construct を分割することでコードの見通しも良くなりました。

以上

この記事をシェアする

関連記事