You can use Resource Orchestration Service (ROS) CDK for TypeScript to create a security group and add rules to the security group.

Step 1: Initialize a project

Each ROS CDK application must be created within an independent project directory. The application uses the dependencies of the modules in the directory. Therefore, you must create a project directory and initialize the project before you create an application.

Run the following commands to create a project directory and initialize the project:

mkdir cdk_demo
cd cdk_demo
ros-cdk init --language=typescript --generate-only=true

Step 2: Configure an Alibaba Cloud credential

  1. Run the following command to configure an Alibaba Cloud credential:
    ros-cdk config
  2. Enter the configuration information.
    endpoint(optional, default:https://ros.aliyuncs.com):
    defaultRegionId(optional, default:cn-hangzhou):cn-beijing
    
    [1] AK
    [2] StsToken
    [3] RamRoleArn
    [4] EcsRamRole
    [0] CANCEL
    
    Authenticate mode [1...4 / 0]: 1
    accessKeyId:************************
    accessKeySecret:******************************
    
     ✅ Your cdk configuration has been saved successfully!

    The following section describes the parameters:

    • endpoint: the endpoint of ROS. Default value: https://ros.aliyuncs.com.
    • defaultRegionId: the ID of the region where the stack is deployed. Default value: cn-hangzhou.
    • Authenticate mode: the authentication method. In this example, an AccessKey pair is used for authentication. You must specify the accessKeyId and accessKeySecret parameters.

Step 3: Install dependencies

  1. Modify the package.json file to add the Elastic Compute Service (ECS) CDK dependency.
    {
      "name": "demo",
      "version": "0.1.0",
      "bin": {
        "demo": "bin/demo.js"
      },
      "scripts": {
        "build": "tsc",
        "test": "jest"
      },
      "devDependencies": {
        "@types/jest": "^25.2.1",
        "@types/node": "10.17.5",
        "typescript": "^3.9.7",
        "jest": "^25.5.0",
        "ts-jest": "^25.3.1",
        "ts-node": "^8.1.0",
        "babel-jest": "^26.6.3",
        "@babel/core": "^7.12.9",
        "@babel/preset-env": "7.12.7",
        "@babel/preset-typescript": "^7.12.7",
        "@alicloud/ros-cdk-assert": "^1.0.0"
      },
      "dependencies": {
        "@alicloud/ros-cdk-core": "^1.0.0",
        "@alicloud/ros-cdk-ecs": "^1.0.0"   
      }
    }
  2. Run the following command to install the dependency:
    npm install

Step 4: Create resources

  1. Modify the lib/demo-stack.ts file to create a security group and add rules to the security group.
    import * as ros from '@alicloud/ros-cdk-core';
    import * as ecs from '@alicloud/ros-cdk-ecs';
    
    export class CdkDemoStack extends ros.Stack {
      constructor(scope: ros.Construct, id: string, props?: ros.StackProps) {
        super(scope, id, props);
        new ros.RosInfo(this, ros.RosInfo.description, "This is the simple ros cdk app example.");
        // The code that defines your stack goes here
      
        const sg = new ecs.SecurityGroup(this, 'ros-cdk-test-sg');
    
        let PortList= ['22','3389','80'];
        for (let port of PortList) {
           new ecs.SecurityGroupIngress(this, `ros-cdk-test-sg-ingress-${port}`, {
            portRange: `${port}/${port}`,
            nicType: 'intranet',
            sourceCidrIp: '0.0.0.0/0',
            ipProtocol: 'tcp',
            securityGroupId: sg.attrSecurityGroupId
          },true);
        }
      }
    }
    Note In the preceding sample code, a for loop is used to create a security group ingress rule (an inbound rule of a security group). This method greatly reduces the amount of code required.
  2. Run the following command to generate a template file:
    ros-cdk synth --json

    The following content is returned after you run the command:

    {
      "Description": "This is the simple ros cdk app example.",
      "ROSTemplateFormatVersion": "2015-09-01",
      "Resources": {
        "ros-cdk-test-sg": {
          "Type": "ALIYUN::ECS::SecurityGroup"
        },
        "ros-cdk-test-sg-ingress-22": {
          "Type": "ALIYUN::ECS::SecurityGroupIngress",
          "Properties": {
            "IpProtocol": "tcp",
            "PortRange": "22/22",
            "NicType": "intranet",
            "Priority": 1,
            "SecurityGroupId": {
              "Fn::GetAtt": [
                "ros-cdk-test-sg",
                "SecurityGroupId"
              ]
            },
            "SourceCidrIp": "0.0.0.0/0"
          }
        },
        "ros-cdk-test-sg-ingress-3389": {
          "Type": "ALIYUN::ECS::SecurityGroupIngress",
          "Properties": {
            "IpProtocol": "tcp",
            "PortRange": "3389/3389",
            "NicType": "intranet",
            "Priority": 1,
            "SecurityGroupId": {
              "Fn::GetAtt": [
                "ros-cdk-test-sg",
                "SecurityGroupId"
              ]
            },
            "SourceCidrIp": "0.0.0.0/0"
          }
        },
        "ros-cdk-test-sg-ingress-80": {
          "Type": "ALIYUN::ECS::SecurityGroupIngress",
          "Properties": {
            "IpProtocol": "tcp",
            "PortRange": "80/80",
            "NicType": "intranet",
            "Priority": 1,
            "SecurityGroupId": {
              "Fn::GetAtt": [
                "ros-cdk-test-sg",
                "SecurityGroupId"
              ]
            },
            "SourceCidrIp": "0.0.0.0/0"
          }
        }
      }
    }

Step 5: Perform a unit test

  1. Modify the test/demo.test.ts file to check whether a security group and multiple security group rules can be created by using a stack.
    import { expect as expectCDK, matchTemplate, MatchStyle } from '@alicloud/ros-cdk-assert';
    import * as ros from '@alicloud/ros-cdk-core';
    import * as CdkDemo from '../lib/cdk_demo-stack';
    
    test('Stack with version.', () => {
      const app = new ros.App();
      // WHEN
      const stack = new CdkDemo.CdkDemoStack(app, 'MyTestStack');
      // THEN
      expectCDK(stack).to(
        matchTemplate(
          {
            "Description": "This is the simple ros cdk app example.",
            "ROSTemplateFormatVersion": "2015-09-01",
            "Resources": {
              "ros-cdk-test-sg": {
                "Type": "ALIYUN::ECS::SecurityGroup"
              },
              "ros-cdk-test-sg-ingress-22": {
                "Type": "ALIYUN::ECS::SecurityGroupIngress",
                "Properties": {
                  "IpProtocol": "tcp",
                  "PortRange": "22/22",
                  "NicType": "intranet",
                  "Priority": 1,
                  "SecurityGroupId": {
                    "Fn::GetAtt": [
                      "ros-cdk-test-sg",
                      "SecurityGroupId"
                    ]
                  },
                  "SourceCidrIp": "0.0.0.0/0"
                }
              },
              "ros-cdk-test-sg-ingress-3389": {
                "Type": "ALIYUN::ECS::SecurityGroupIngress",
                "Properties": {
                  "IpProtocol": "tcp",
                  "PortRange": "3389/3389",
                  "NicType": "intranet",
                  "Priority": 1,
                  "SecurityGroupId": {
                    "Fn::GetAtt": [
                      "ros-cdk-test-sg",
                      "SecurityGroupId"
                    ]
                  },
                  "SourceCidrIp": "0.0.0.0/0"
                }
              },
              "ros-cdk-test-sg-ingress-80": {
                "Type": "ALIYUN::ECS::SecurityGroupIngress",
                "Properties": {
                  "IpProtocol": "tcp",
                  "PortRange": "80/80",
                  "NicType": "intranet",
                  "Priority": 1,
                  "SecurityGroupId": {
                    "Fn::GetAtt": [
                      "ros-cdk-test-sg",
                      "SecurityGroupId"
                    ]
                  },
                  "SourceCidrIp": "0.0.0.0/0"
                }
              }
            }
          },
          MatchStyle.EXACT,
        ),
      );
    });
  2. Run the following command to perform a unit test:
    npm test

    The following content is returned after you run the command:

    > cdk_demo@0.1.0 test /home/cdk_demo
    > jest
    
     PASS  test/cdk_demo.test.ts
      ✓ Stack with version. (249ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        4.685s
    Ran all test suites.

Step 6: Manage stacks

You can create, query, or delete stacks by running ROS CDK commands.

  • Create a stack

    Run the following command to create a stack:

    ros-cdk deploy

    The following content is returned after you run the command:

    ✅ The deployment(create stack) has completed!
    RequestedId: BC963C80-054D-41A0-87E7-001E0AB7B1BA
    StackId: 0714be3a-0713-4b7d-b7aa-1564adef****
  • Query information about a stack

    Run the following command to query information about a stack:

    ros-cdk list-stacks

    The following content is returned after you run the command:

     ✅ The Stacks list is:
     [
            {
                    "Status": "CREATE_COMPLETE",
                    "StackType": "ROS",
                    "StatusReason": "Stack CREATE completed successfully",
                    "CreateTime": "2021-01-26T12:58:05",
                    "RegionId": "cn-beijing",
                    "DisableRollback": false,
                    "StackName": "CdkDemoStack",
                    "Tags": [],
                    "StackId": "218f0db0-7992-4e70-a586-15d****",
                    "TimeoutInMinutes": 20
            }
    ]
  • Delete a stack
    1. Run the following command to delete a stack:
      ros-cdk destroy
    2. Confirm the deletion operation.
      The following stack(s) will be destroyed(Only deployed stacks will be displayed).
      CdkDemoStack
      
      Please confirm.(Y/N)
      Y

      The following content is returned after you run the command:

       ✅ Deleted
      RequestedId: 1BF864E1-7965-4148-A302-E6ABFF806641