CDK で Amplify 読み取り用 S3 を作る際のはまりどころ

CDK で Amplify Hosting 手動デプロイ用の S3 バケットを作ったときにつまずいた点の記録。バケット名の 63 文字制限、SourceArn への encodeURIComponent、スタックの env 明示の 3 つ。

広告ここから
広告ここまで

目次

    AWS Amplify Hosting の手動デプロイ(BUCKET_PREFIX)向けに、CDK で S3 バケットと Amplify 読み取り用のバケットポリシーを作りました。その際に引っかかった点についていくつかまとめました。

    1: バケット名は 63 文字以内

    S3 バケット名は 63 文字以内です。スタック ID 全体の UUID(36 文字)をサフィックスに含めると、すぐ上限を超えます。

    例えばプレフィックス amplify-s3-deploy-123456789012- の時点で 30 文字を超えており、UUID 全体を足すとデプロイが失敗します。

    CREATE_FAILED | AWS::S3::Bucket | ArtifactBucket
    "Bucket name should be between 3 and 63 characters long"
    

    回避策として、スタック ID から取り出すサフィックスを UUID の先頭セグメント(8 文字)だけにします。

    const stackId = cdk.Stack.of(this).stackId;
    // スタック ID の UUID 先頭セグメント(8 文字)のみ使う
    const stackSuffix = cdk.Fn.select(
      0,
      cdk.Fn.split("-", cdk.Fn.select(2, cdk.Fn.split("/", stackId))),
    );
    
    const bucketName = `amplify-s3-deploy-${this.account}-${stackSuffix}`;
    

    2: SourceArn では encodeURIComponent を使わない

    スタックに env を指定しないと、CDK は cdk synth の時点でデプロイ先のアカウント ID とリージョンを知りません。

    このとき cdk.Stack.of(this).account が返すのは、本物のアカウント ID ではなく ${Token[AWS.AccountId.0]} という仮の文字列です。region も同じです。CDK はこの仮の文字列を、テンプレート出力時に { "Ref": "AWS::AccountId" } に置き換えます。

    ここに encodeURIComponent を通すと、仮の文字列が %24%7BToken%5B... のように変換されます。CDK はこれを仮の文字列として認識できず、置き換えられないままテンプレートに残ります。バケットポリシーの aws:SourceArn は、デプロイ時の値が必要な箇所です。ここは cdk.Fn.sub() に切り替えると安全です。

    conditions: {
      StringEquals: {
        "aws:SourceArn": cdk.Fn.sub(
          "arn:aws:amplify:${AWS::Region}:${AWS::AccountId}:apps/${AppId}/branches/*",
          { AppId: props.amplifyAppId },
        ),
      },
    },
    

    まとめ

    バケット名のサフィックスに UUID 全体を使うと 63 文字の上限を超えるので、先頭の 8 文字だけを使います。

    aws:SourceArn のようにデプロイ時の値が必要な箇所では、アカウント ID やリージョンの文字列に encodeURIComponent をつかわず、cdk.Fn.sub() を使いましょう。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark