Open9

CDKのTips

Naoyuki YamadaNaoyuki Yamada

SecurityGroupのインポート

外部で定義してあるセキュリティグループをインポートするには、3つのメソッドがある。

  • fromLookupById
  • fromLookupByName
  • fromSecurityGroupId

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2.SecurityGroup.html#static-fromwbrlookupwbrbywbridscope-id-securitygroupid

このうちfromSecurityGroupIdにはImportOptionをつけることができ、allowAllOutboundでoutbound traffic(Egress)のオン・オフができる。

fromLookupById または fromLookupByName で読み込んだ際には、allowAllOutboundはLookupの結果によって判定され、cdk.context.jsonファイルに格納される。

  "security-group:account=xxxxx:region=ap-northeast-1:securityGroupName=xxxxxSecurityGroup:vpcId=vpc-xxxxx": {
    "securityGroupId": "sg-xxxxx",
    "allowAllOutbound": false
  },

ここでallowAllOutboundがtrueになるかfalseになるかは
https://github.com/aws/aws-cdk/blob/5706655a3873c232deab4542f53c91c4e69b3695/packages/aws-cdk/lib/context-providers/security-groups.ts#L59
で判定されており、ipv4とipv6の両方がすべてのプロトコルとIPで許可されている必要がある。

この条件がけっこう厳しくて、普通にセキュリティグループを作った際には、ipv4のほうしかルールが定義されないので、ここがfalseになりがち。

ここがfalseになると、

{なにかのリソース}.connections.allowFrom({インポートしたセキュリティグループ}, Tcp.port(xx))

みたいに許可ルールを書いたときに、インポートしたセキュリティグループ側のEgressルールが書き換わってしまう。
これを回避するには、

(1)fromSecurityGroupId でインポートする。ただしセキュリティグループの名前でimportしたい場合には使い勝手が悪い。
(2)セキュリティグループを作ったあとに、ipv4とipv6両方のトラフィックを全許可するEgressルールを明示的に追加しておく。

Naoyuki YamadaNaoyuki Yamada

RDS(Aurora)作成時のEngineバージョンの明示的な指定

DBクラスターをつくるときに、MySQLかPostgreSQLかと、そのバージョンを選択するが、

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_rds.DatabaseClusterEngine.html

engine: DatabaseClusterEngine.AURORA_POSTGRESQL

みたいに指定してしまうと、適当なバージョンがあてられてしまう。
ドキュメントに書いてあるとおり、この指定はnot recommendedなので、

 engine: DatabaseClusterEngine.auroraPostgres({
      version: AuroraPostgresEngineVersion.VER_13_4,
  }),

のように書けば、明示的にバージョン指定できる。

Naoyuki YamadaNaoyuki Yamada

Aurora PostgreSQLのパスワード生成に使う文字種を限定する

https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_secretsmanager.SecretStringGenerator.html#excludepunctuation

excludepunctuationというオプションがあり、Cloudformationの

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-secretsmanager-secret-generatesecretstring.html#cfn-secretsmanager-secret-generatesecretstring-excludepunctuation

と対応している。
不具合につながる記号を含んだパスワードを生成するのを回避してくれる。

DatabaseSecret経由でパスワードを作るとこのオプションが使えないので

excludeCharacters: `#$%&'"()*+,-./:;<=>?@[\\]^_\`{|}~`,

このように指定すると同様のことができる。

Naoyuki YamadaNaoyuki Yamada

SecretsManagerを消すときは、既存のスタックから参照を消してからにするように注意する。

参照が残ったまま消すと、

Secrets Manager can't find the specified secret. (Service: AWSSecretsManager; Status Code: 400; Error Code: ResourceNotFoundException;

このエラーでスタックの更新が失敗するようになってしまう。
スタックは更新するときに、まず変更前のテンプレートの解決をしようとしてしまうため。

Naoyuki YamadaNaoyuki Yamada

aws-lambda-nodejs でtop level awaitを使う

コードの中でtop level awaitのコードを入れたら

Top-level await is currently not supported with the "cjs" output format

が出てビルドできず困っていたが、

new NodejsFunction(
    (中略)
    bundling: {
      format: OutputFormat.ESM,
    },
  }
)

でいけた。

Naoyuki YamadaNaoyuki Yamada

lambdaFunctionでエラーが出たら通知するCloudwatch Alarm

lambdaFunction
    .metricErrors()
    .createAlarm(this, 'LambdaErrorAlarm', {
        threshold: 0,
        evaluationPeriods: 1,
        alarmName: `${projectName}-LambdaErrorAlarm`,
        alarmDescription: 'LambdaErrorAlarm',
        comparisonOperator: aws_cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
        treatMissingData: aws_cloudwatch.TreatMissingData.NOT_BREACHING,
        actionsEnabled: true,
    })
    .addAlarmAction(new aws_cloudwatch_actions.SnsAction(this.alertSnsTopic))

これだけでいい。
aws chatbotでslack連携して対象のsnsTopicをsubscribeしておけば、上記だけでslack通知される。

Naoyuki YamadaNaoyuki Yamada

StepFunctionsでCallAwsServiceでQueryは使えない。resultSelectorで絞り込める

ec2.desribeInstancesはそのままだと返すフィールドが多いので、StepFunctionsで扱えるデータ上限を超えがち。
なのでec2.describeInstancesでqueryで結果を絞り込みたいと思ったら

Invalid State Machine Definition: 'SCHEMA_VALIDATION_FAILED: The field "Query" is not supported by Step Functions. Did you mean 'Filters'

resultSelectorが使えるのでそちらを使う。

aws-cdk-lib.aws_stepfunctions module · AWS CDK