How to Import Security group from another stack using #AWS-CDK?

Viewed 13837

I would like to know how to import security group defined in another stack, and then use in current stack.

I have tried this so far..

class relayStack extends cdk.Stack {
    public sg_relay: ec2.SecurityGroupRefProps

    constructor(parent: cdk.App, name: string, props: VPCProps) {
        super(parent, name, props);

        //#IMPORT VPC PROPS
        const vpc = ec2.VpcNetwork.import(this, 'VPC-Hottest100', props.infra.vpc);
        //#AUTOSCALING GROUP
        const asg_relayServer = new ec2.AutoScalingGroup(this, 'ASG_Relay', {
            vpc,
            instanceType: new ec2.InstanceTypePair(ec2.InstanceClass.T2, ec2.InstanceSize.Small),
            minSize: 1,
            maxSize: 3,
            desiredCapacity: 1,
            machineImage: new ec2.GenericLinuxImage({
                "ap-southeast-2": "ami-dc361ebf",
            }),
            keyName: 'icecast-poc',
            allowAllOutbound: false,
            vpcPlacement: {
                usePublicSubnets: false
            }
        });

        //#SECURITY Group
        const sg_relay = new ec2.SecurityGroup(this, 'SG_RELAY', {
            vpc,
            description: "Relay stack security group",
            groupName: 'relay-sg'
        })


        this.sg_relay = sg_relay
    }
}

And then from another stack I would like to access the exported security group sg_relay

I have tried following

//#SECURITY GROUP
const sg_nginx = new ec2.SecurityGroup(this, "SG_NGINX", {
    vpc,
    description: "NGINX stack security group",
    groupName: 'nginx-sg'
})

const sg_relayImp = new ec2.SecurityGroupRef(this, "SG_RELAY_IMP", {
    securityGroupId: new ec2.SecurityGroupId('SG_RELAY')
})

And then use as following

sg_nginx.addIngressRule(sg_relayImp, wowzaPort, 'asg_RelyToNgn_8000')

Obviously its not working for me.

I could not find any import function for security group between stacks, like vpc has one.

Could anyone please help me with this situation?

4 Answers

You can directly refer the cross-stack resources in an app.

Below is a code snippet,

export class InfraCdkStack extends cdk.Stack {
  // Create a readonly property to reference on an instance.
  readonly vpc: ec2.IVpc;

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

    // The code that defines your stack goes here.
    // Assign your vpc to your previously created property.
    // Creates a vpc in two AZs.
    this.vpc = new ec2.Vpc(this, 'MyVPC');
  }
}

// Create an interface to hold the vpc information.
interface ECSStackProps extends cdk.StackProps {
  vpc: ec2.IVpc;
}

// Have your class constructor accept the interface.
export class ECSCdkStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props: ECSStackProps) {
    super(scope, id, props);
}

const app = new cdk.App();
const infraStack = new InfraCdkStack(app, 'InfraCdkStack');
// Pass the infraStack.vpc property to the ECSCdkStack class.
const gameECSStack = new ECSCdkStack(app, 'ECSCdkStack', {
    vpc: infraStack.vpc
});

There is an example in official doc to demonstrate how sharing s3 bucket.

Assuming that the Stacks in question are both under your CDK Application, you can use Stack Outputs to share resources.

Docs here: https://docs.aws.amazon.com/cdk/api/latest/docs/core-readme.html#stack-outputs

I found this blog post to be useful as an example (not written by me)

It should work for any resource you might want to reference between stacks.

EDIT: This is what I'm working with at the moment.

// I have a resource which is a cloudfront dist id in StackA
new cdk.CfnOutput(this, 'cloudfront-dist-id-output', {
      description: 'cloudfront-dist-id-output',
      exportName: 'cloudfront-dist-id-output',
      value: cloudFrontDistribution.distributionId
    });

// Stack B needs the DistributionId (it's dynamic), so I pass it in as a parameter.
new StackB(app, 'StackB', Fn.importValue('cloudfront-dist-id-output'));

The only 'known' thing ahead of time is the name of the parameter that you're outputting.

This is effectively the same thing you've provided in your other answer, but the CDK writes the Fn.importValue for you.

Warning: Does not work with resources in stacks that are in different regions. The limitation is imposed by CloudFormation and will also happen in @Kane's answer.

Create a sample security group like this in STACK A.

const sampleSecurityGroup = new ec2.SecurityGroup(this, 'security-group', { vpc: vpc, allowAllOutbound: true, description: 'Security Group Sample', securityGroupName: "SAMPLE-SG" });

Export the SG using below in STACK A.

const myoutput = new cdk.CfnOutput(this, 'Security-group-id-output', { description: 'Security group in Stack A', exportName: 'security-id-output', value: sampleSecurityGroup.securityGroupId });

Check the Cloud formation service in in UI you should see the Exports by the name "security-id-output".

In STACK B import the value using

cdk.Fn.importValue("security-id-output");

You could use SecurityGroup.export in the stack that defines the security group initially, and this will create a stack Output with a generated export name, and return the data that you need to pass to SecurityGroupRef.import in order to obtain a reference to the security group in the other stack.

You'll need to be sure to deploy the stack that defines the security group first, as otherwise the other stack will not be able to import from that stack's outputs.

Related