つまったところ
PythonでCDK実装していて、セキュリティグループのルール作成時にエラーが出ました。。
その解消方法をメモに残します。
前提
-
実装状況:
セキュリティグループを定義するDemoStack
を作成し、
cdk synth DemoStack
コマンドは実行(CloudFormationテンプレートの生成まで完了)できている状態です。
class DemoStack(cdk.Stack):
def __init__(self, scope: cdk.App, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
## VPCリソースの参照
vpc = ec2.Vpc.from_lookup(self, "VPC", vpc_id = xxxxxx)
## 各種セキュリティグループリソースの作成
# SecurityGroup1
sample_sg_1 = ec2.SecurityGroup(self, "SampleSecurityGroupOne",
vpc = vpc,
security_group_name = "sample-sg-one"
)
# SecurityGroup2
sample_sg_2 = ec2.SecurityGroup(self, "SampleSecurityGroupTwo",
vpc = vpc,
security_group_name = "sample-sg-two"
)
# SecurityGroup3
sample_sg_3 = ec2.SecurityGroup(self, "SampleSecurityGroupThree",
vpc = vpc,
security_group_name = "sample-sg-three"
)
最初に書いていたインバウンドルール設定
# SG1 → SG2のインバウンドルールを設定
sample_sg_2.add_ingress_rule(
peer=ec2.Peer.security_group_id(sample_sg_1.security_group_id),
connection=ec2.Port.all_traffic()
)
# SG3 → SG2のインバウンドルールを設定
sample_sg_2.add_ingress_rule(
peer=ec2.Peer.security_group_id(sample_sg_3.security_group_id),
connection=ec2.Port.all_traffic()
)
# SG1 → SG3のインバウンドルールを設定
sample_sg_3.add_ingress_rule(
peer=ec2.Peer.security_group_id(sample_sg_1.security_group_id),
connection=ec2.Port.all_traffic()
)
# SG2 → SG3のインバウンドルールを設定
sample_sg_3.add_ingress_rule(
peer=ec2.Peer.security_group_id(sample_sg_2.security_group_id),
connection=ec2.Port.all_traffic()
)
Circular dependency between resources: [SampleSecurityGroupTwoA53ACEDA, SampleSecurityGroupThree2035AAB5]
エラーが出ました。SG2とSG3がCircular dependency(循環依存)
と指摘されています。
SG2 ⇔ SG3が参照しあっているのが原因みたいです。。でもこうしたい。。
循環依存?
公式CDKAPIドキュメントによると、connections属性を使って、インバウンド・アウトバウンド設定を記述すると良いとのことです。
CDK APIリファレンス(Allowing Connections)
(ブラウザ日本語翻訳)
セキュリティ グループの更新に便利なオブジェクトである、 connectionsという属性があります。セキュリティ グループを持つ 2 つのコンストラクト間の接続を許可する場合は、 1 つのセキュリティ グループにEgressルールを追加し、もう 1 つのセキュリティ グループにIngressルールを追加する必要があります。 connections オブジェクトは、これを自動的に処理します。
インバウンドルールを設定する場合のサンプルコードも書いてありました。
// The same, but an explicit IP address
loadBalancer.connections.allowFrom(ec2.Peer.ipv4('1.2.3.4/32'), ec2.Port.HTTPS, 'Allow inbound HTTPS');
pythonではconnections.allow_from
を使うと良さそうです。
修正内容
# SG1 → SG2のインバウンドルールを設定
sample_sg_2.connections.allow_from(
sample_sg_1,
ec2.Port.all_traffic()
)
# SG3 → SG2のインバウンドルールを設定
sample_sg_2.connections.allow_from(
sample_sg_3,
ec2.Port.all_traffic()
)
# SG1 → SG3のインバウンドルールを設定
sample_sg_3.connections.allow_from(
sample_sg_1,
ec2.Port.all_traffic()
)
# SG2 → SG3のインバウンドルールを設定
sample_sg_3.connections.allow_from(
sample_sg_2,
ec2.Port.all_traffic()
)
✅ DemoStack: destroyed
無事deployできました!