概要
AWS CDK v2.237.1は、Java環境での重大なバグを修正するパッチリリースです。v2.234.0以降、JavaでCloudFormation組み込み関数(Fn::Ifなど)を含むトークンを文字列連結した場合に、トークンとして正しく認識されず、文字列の長さ検証で失敗する問題がありました。このリリースでは、jsii-pacmakのバージョンアップにより問題が解決されています。
バグ修正
Core: JavaでCloudFormation組み込み関数トークンが正しく検出されない問題を修正 (#36843)
JavaでICfnRuleConditionExpression(Fn::If、Fn::Equalsなどの条件式)を文字列連結して使用した際に、CDKがトークンとして認識せず、文字列そのものの長さで検証を行ってしまう問題が修正されました。
問題の詳細
v2.234.0以降、Javaで以下のようなコードを実行すると、domainNameがトークンではなく文字列として評価され、64文字を超えるためバリデーションエラーが発生していました。
// 問題が発生していたコード
CfnCondition hasSubdomain = CfnCondition.Builder.create(this, "hasSubdomain")
.expression(Fn.conditionNot(Fn.conditionEquals(subdomain, "")))
.build();
// Fn::If条件式を作成
ICfnRuleConditionExpression qualifiedDomain =
Fn.conditionIf(hasSubdomain.getLogicalId(), subdomain + "myapp.cloud", "myapp.cloud");
// 文字列連結でトークンを使用
Certificate.Builder.create(this, "somecert")
.domainName("*." + qualifiedDomain) // ここでエラーが発生していた
.validation(CertificateValidation.fromDns(zone))
.build();
エラーメッセージ:
software.amazon.jsii.JsiiError: Domain name must be 64 characters or less
原因
この問題はjsii-pacmakの内部実装に起因していました。JavaのプロキシクラスでtoString()メソッドがJavaScript側の実装を呼び出さず、Java側のデフォルト実装を使用していたため、トークンの文字列表現(${Token[...]}形式)ではなく、オブジェクトのデフォルトtoString()結果(クラス名とハッシュコード)が返されていました。
CDKはトークンを検出するために文字列表現を使用しているため、正しいtoString()が呼ばれないとトークンとして認識されず、文字列の長さ検証がそのまま適用されてしまいます。
修正内容
jsii-pacmakのバージョンが更新され、プロキシクラスのtoString()メソッドが正しくJavaScript側の実装を呼び出すようになりました。これにより、ICfnRuleConditionExpressionなどのインターフェースプロキシでも正しくトークン文字列が返されるようになりました。
修正後の動作
修正後は、Fn::Ifなどの条件式を含むトークンが正しく認識され、CloudFormationテンプレートに正しく出力されます:
import software.amazon.awscdk.*;
import software.amazon.awscdk.services.certificatemanager.Certificate;
import software.amazon.awscdk.services.certificatemanager.CertificateValidation;
import software.amazon.awscdk.services.route53.IPublicHostedZone;
public class MyStack extends Stack {
public MyStack(final Construct scope, final String id, final StackProps props) {
super(scope, id, props);
String myappDomain = "myapp.cloud";
// サブドメインパラメータ
CfnParameter subdomain = CfnParameter.Builder.create(this, "subdomain")
.type("String")
.description("サブドメイン(dev、qaなど)。空欄の場合は本番環境")
.build();
// サブドメインの有無を判定する条件
CfnCondition hasSubdomain = CfnCondition.Builder.create(this, "hasSubdomain")
.expression(Fn.conditionNot(Fn.conditionEquals(subdomain.getValueAsString(), "")))
.build();
// 条件に基づいてドメイン名を決定
// Fn::Ifを使用して、サブドメインがある場合とない場合でドメインを切り替え
ICfnRuleConditionExpression qualifiedDomain = Fn.conditionIf(
hasSubdomain.getLogicalId(),
subdomain.getValueAsString() + "." + myappDomain, // サブドメインあり: dev.myapp.cloud
myappDomain // サブドメインなし: myapp.cloud
);
// ワイルドカード証明書の作成
// v2.237.1では正しくトークンとして認識され、バリデーションエラーは発生しない
Certificate.Builder.create(this, "Certificate")
.domainName("*." + qualifiedDomain) // *.dev.myapp.cloud または *.myapp.cloud
.validation(CertificateValidation.fromDns(zone))
.build();
}
}
生成されるCloudFormationテンプレート(抜粋):
{
"Resources": {
"Certificate": {
"Type": "AWS::CertificateManager::Certificate",
"Properties": {
"DomainName": {
"Fn::Join": [
"",
[
"*.",
{
"Fn::If": [
"hasSubdomain",
{ "Fn::Join": ["", [{"Ref": "subdomain"}, ".myapp.cloud"]] },
"myapp.cloud"
]
}
]
]
}
}
}
}
}
影響を受けるバージョン
- 影響を受けるバージョン: v2.234.0 〜 v2.237.0
- 最後に正常動作していたバージョン: v2.233.0
- 修正されたバージョン: v2.237.1
影響を受ける言語
この問題はJava固有のものです。TypeScript、Python、C#、Goでは発生しません。
Alphaモジュール (2.237.1-alpha.0)
このリリースのAlphaモジュールには新機能やバグ修正はありません。
まとめ
AWS CDK v2.237.1は、Java環境でCloudFormation組み込み関数トークンが正しく検出されない重大なバグを修正するパッチリリースです。
v2.234.0以降、JavaでFn::Ifなどの条件式を文字列連結して使用すると、Certificate Managerなどの文字列長検証でエラーが発生していました。このリリースではjsii-pacmakのバージョンアップにより、インターフェースプロキシのtoString()メソッドが正しくJavaScript側の実装を呼び出すようになり、問題が解決されました。
Javaを使用していてv2.234.0〜v2.237.0でこの問題に遭遇していた場合は、v2.237.1へのアップグレードを推奨します。