AWSで何にするにしてもcdkの方がよかったという話

に公開

bootstrapは実行済みとする

やりたいこと

  • costという名前のユーザーを作る
  • AWSBillingReadOnlyAccessを割り当てる
  • keyとsecretを出す

gitリポジトリを作る

これだけのためにgithubだのgitlabだののprojectを1つ作るのか、何かしら統合するのかは適当に考える必要があるが今回は作成した

npm

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -

# Node.js + npm のインストール
sudo apt-get install -y nodejs

sudo npm install -g aws-cdk

$ cdk --version
2.1018.1 (build cb71364)

こんな感じでcdkが使えるようになっていること

cloneしてきた空のプロジェクトにinit

npx cdk init app --language=typescript

そうするとこうなる

$ git status
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        .npmignore
        README.md
        bin/
        cdk.json
        jest.config.js
        lib/
        package-lock.json
        package.json
        test/
        tsconfig.json

nothing added to commit but untracked files present (use "git add" to track)
git add .
git commit -m "Initialize CDK project with TypeScript"
git push origin main

とかして投入しておく

stack作る

lib/cost-cdk-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam';

/**
 * CostCdkStack:
 * AWSのコスト確認専用のIAMユーザー "cost" を作成し、
 * 読み取り専用の課金権限 (AWSBillingReadOnlyAccess) を付与。
 * 同時にアクセスキーも発行して、CloudFormationのOutputsで出力する。
 */
export class CostCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // IAMユーザー "cost" を作成
    const user = new iam.User(this, 'CostUser', {
      userName: 'cost', // IAMユーザー名
    });

    // AWSの課金情報を読み取るためのマネージドポリシーを付与
    user.addManagedPolicy(
      iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBillingReadOnlyAccess')
    );

    // アクセスキー(AccessKeyId と SecretAccessKey)を作成
    const accessKey = new iam.CfnAccessKey(this, 'CostUserAccessKey', {
      userName: user.userName,
    });

    // AccessKeyId の出力
    new cdk.CfnOutput(this, 'AccessKeyId', {
      value: accessKey.ref,
      description: 'Access key ID for the cost user',
    });

    // SecretAccessKey の出力(非常に重要。必ず安全な場所に保管を)
    new cdk.CfnOutput(this, 'SecretAccessKey', {
      value: accessKey.attrSecretAccessKey,
      description: 'Secret access key for the cost user (only shown once)',
    });
  }
}

この辺のコードはAIに書かせてもいいけど、コメントもちゃんと添えてある程度理解して配置すること

さらにbinの下も正しく当該classを指定するようにする

#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { CostCdkStack } from '../lib/cost-cdk-stack';

const app = new cdk.App();
new CostCdkStack(app, 'CostCdkStack');

最低限

npx tsc --noEmit

くらいしといてcommit

$ git add .
$ git commit -m 'Add IAM user 'cost' with billing read-only access and access key outputs'
[main 1b822b3] Add IAM user cost with billing read-only access and access key outputs
 1 file changed, 42 insertions(+)
 create mode 100644 lib/cost-cdk-stack.ts
$ git push origin main  

的な感じでcommit & pushする

適用する

これは当該アカウントのadminのcloudshellでやるとよい。cloudshellからgit cloneしてcdする

ここで

npm install

する

synth

とりあえず

 npx cdk synth

しておく。するとyamlが出てくるが見辛いのでAIに食わせておくのがよいだろう

実行する

npx cdk deploy

成功するとkeyとsecretが出てくる。もちろんsecretはこの時点で控える

確認する


よさそう

まとめ

ユーザー作ったり権限割り当てたり独自ポリシー作ったりっていうのは割と作りっぱなしになってしまいがちなのでコードに残るというのが結構重要かも。terraformでやってもいいんでしょうが、こういうのはなんだかんだcdkの方が取り回しはいいかなと感じました。

Discussion