Skip to content

(ec2): Python class implementing aws_ec2.IConnectable fails when using connections.allow_ methods #4726

Open
@cpitchford

Description

@cpitchford

Describe the bug

I have found that using an object created from Construct sub-class that implements ec2.IConnectable (by having an ec2.Connections property connections) doesn't work when used with other connections.

The connections property can be use directly but the IConnectable object causes an error.

This does not appear to be the case when re-written in typescript

from aws_cdk import Stack
from aws_cdk import aws_ec2 as ec2
from constructs import Construct

from typing import Any

# an ec2.IConnectable class, wrapping an ec2.Connections object

class MyIConnectable(Construct):
    connections: ec2.Connections
    def __init__(self, scope: Construct, id: str, connections: ec2.Connections):
        super().__init__(scope,id)
        self.connections = connections



class TestCdkConnectionsStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs:Any) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # Create security groups

        service_sg = ec2.SecurityGroup.from_security_group_id(
            self, "service_sg",
            security_group_id="sg-123456789012",
            allow_all_outbound=True,
            mutable=True
        )

        clients_sg = ec2.SecurityGroup.from_security_group_id(
            self, "clients_sg",
            security_group_id="sg-111111111111",
            allow_all_outbound=True,
            mutable=True
        )

        # Create connections using the security groups

        service_connections=ec2.Connections(
            default_port=ec2.Port.tcp_range(
                start_port=8000,
                end_port=9000
            ),
            security_groups=[
                service_sg
            ]
        )

        clients_connections=ec2.Connections(
            default_port=ec2.Port.tcp(port=22),
            security_groups=[
                clients_sg
            ]
        )

        # Create IConnectable objects using the connections

        service: ec2.IConnectable = MyIConnectable(self, "service connections", service_connections)
        clients: ec2.IConnectable = MyIConnectable(self, "clients connections", clients_connections)

        # Try to connect to the IConnectable together. Error occurs

        service.connections.allow_default_port_from(
            other=clients,
            description="test"
        )

In Typescript:

import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2'
import { Construct } from 'constructs';



//an ec2.IConnectable class, wrapping an ec2.Connections object

class MyIConnectable extends Construct implements ec2.IConnectable {
  connections: cdk.aws_ec2.Connections;
  constructor(scope: Construct, id: string, connections: ec2.Connections) {
    super(scope, id)
    this.connections=connections
  }
}

export class TestCdkConnectionsStack extends cdk.Stack {

  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create security groups

    let service_sg = ec2.SecurityGroup.fromSecurityGroupId(
      this, "service_sg", "sg-111111111111", {
        allowAllOutbound: true,
        mutable: true
      }
    )

    let clients_sg = ec2.SecurityGroup.fromSecurityGroupId(
      this, "client_sg", "sg-222222222222", {
        allowAllOutbound: true,
        mutable: true
      }
    )

    // Create connections using the security groups

    let service_connections=new ec2.Connections({
      defaultPort:ec2.Port.tcpRange(
        22,
        65535
      ),
      securityGroups:[
        service_sg
      ]
    })

    let clients_connections=new ec2.Connections({
        defaultPort:ec2.Port.tcp(3389),
        securityGroups:[
          clients_sg
        ]
      })

    // Create IConnectable objects using the connections

    let service = new MyIConnectable(this, "service connection", service_connections)
    let clients = new MyIConnectable(this, "clients connection", clients_connections)

    // Try to connect to the IConnectable together. Works as expected

    service.connections.allowDefaultPortFrom(
      clients,
      "Test"
    )

  }
}

Regression Issue

  • Select this option if this issue appears to be a regression.

Last Known Working CDK Version

No response

Expected Behavior

I expect the python and typescript versions to behave in the same way. I expect to be able to pass my ec2.IConnectable class into ec2.Connections.allow_from(other=my_class_object)

Current Behavior

In python I see an error returned when I try to use my ec2.IConnectable class object:

cdk synth
jsii.errors.JavaScriptError: 
  @jsii/kernel.RuntimeError: TypeError: Cannot read properties of undefined (reading '_securityGroupRules')
      at Kernel._Kernel_ensureSync (/tmp/tmp1mctuqbv/lib/program.js:9510:23)
      at Kernel.invoke (/tmp/tmp1mctuqbv/lib/program.js:8874:102)
      at KernelHost.processRequest (/tmp/tmp1mctuqbv/lib/program.js:10715:36)
      at KernelHost.run (/tmp/tmp1mctuqbv/lib/program.js:10675:22)
      at Immediate._onImmediate (/tmp/tmp1mctuqbv/lib/program.js:10676:46)
      at process.processImmediate (node:internal/timers:491:21)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/cdk/test_cdk_connections/app.py", line 10, in <module>
    TestCdkConnectionsStack(app, "TestCdkConnectionsStack",
  File "/cdk/test_cdk_connections/.venv/lib/python3.12/site-packages/jsii/_runtime.py", line 118, in __call__
    inst = super(JSIIMeta, cast(JSIIMeta, cls)).__call__(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/cdk/test_cdk_connections/test_cdk_connections/test_cdk_connections_stack.py", line 64, in __init__
    service.connections.allow_default_port_from(
  File "/cdk/test_cdk_connections/.venv/lib/python3.12/site-packages/aws_cdk/aws_ec2/__init__.py", line 93016, in allow_default_port_from
    return typing.cast(None, jsii.invoke(self, "allowDefaultPortFrom", [other, description]))
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/cdk/test_cdk_connections/.venv/lib/python3.12/site-packages/jsii/_kernel/__init__.py", line 149, in wrapped
    return _recursize_dereference(kernel, fn(kernel, *args, **kwargs))
                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/cdk/test_cdk_connections/.venv/lib/python3.12/site-packages/jsii/_kernel/__init__.py", line 399, in invoke
    response = self.provider.invoke(
               ^^^^^^^^^^^^^^^^^^^^^
  File "/cdk/test_cdk_connections/.venv/lib/python3.12/site-packages/jsii/_kernel/providers/process.py", line 380, in invoke
    return self._process.send(request, InvokeResponse)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/cdk/test_cdk_connections/.venv/lib/python3.12/site-packages/jsii/_kernel/providers/process.py", line 342, in send
    raise RuntimeError(resp.error) from JavaScriptError(resp.stack)
RuntimeError: TypeError: Cannot read properties of undefined (reading '_securityGroupRules')

Reproduction Steps

Checkout https://github.com/cpitchford/cdk-iconnectable-python

bash test_python.py

see error line here: python/iconnectable-test/iconnectable_test/iconnectable_test_stack.py

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.173.0 (build b5c2189)

Framework Version

No response

Node.js Version

v22.12.0

OS

Linux (Ubuntu 24.04) and MacOS (15.2)

Language

Python

Language Version

python (3.12.3)

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue is a bug.p2

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions