CDK Pythonでセキュリティグループ作成時のエラー

# つまったところ
PythonでCDK実装していて、セキュリティグループのルール作成時にエラーが出ました。。
その解消方法をメモに残します。



# 前提
* 作りたいもの：各種インバウンドルール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/9d7fe304-8018-8b9f-c465-45cfb21a2607.png)



* 実装状況：
セキュリティグループを定義する<code>DemoStack</code>を作成し、
<code>cdk synth DemoStack</code>コマンドは実行（CloudFormationテンプレートの生成まで完了）できている状態です。
```code:demo_stack.py抜粋
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"
        )

```



# 最初に書いていたインバウンドルール設定

```code:
        # 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()
        )
```


```code:出力結果
Circular dependency between resources: [SampleSecurityGroupTwoA53ACEDA, SampleSecurityGroupThree2035AAB5]
```

エラーが出ました。SG2とSG3が<code>Circular dependency(循環依存)</code>と指摘されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618752/44863930-8621-3a94-a8c8-4715eedd180f.png)
SG2 ⇔ SG3が参照しあっているのが原因みたいです。。でもこうしたい。。


# 循環依存？
公式CDKAPIドキュメントによると、connections属性を使って、インバウンド・アウトバウンド設定を記述すると良いとのことです。
[CDK APIリファレンス(Allowing Connections)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#allowing-connections "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では<code>connections.allow_from</code>を使うと良さそうです。


# 修正内容
```code:インバウンドルールの記述を修正
        # 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()
        )
```


```code:cdk deploy実行結果

 ✅  DemoStack: destroyed

```
無事deployできました！


# 参考
[CDK APIリファレンス(SecurityGroup)](https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_ec2/SecurityGroup.html "SecurityGroup")


[CDK APIリファレンス(Allowing Connections)](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_ec2-readme.html#allowing-connections "Allowing Connections")