Desktop and Application Streaming

Automatically attach additional security groups to Amazon AppStream 2.0 and Amazon WorkSpaces

Both Amazon AppStream 2.0 and Amazon WorkSpaces have a default security group to attach to new instances. In highly regulated and controlled environments, a single security group does not always meet security requirements of the organization. Centrally managed security policies require attaching multiple security groups that are controlled by the security or other team. In addition, multiple security groups can be necessary due to the limits on the number of rules for a single security group.

Overview

In this post, you learn how to automate attaching additional security groups to elastic network interfaces (ENI) for new Amazon AppStream 2.0 fleet instances and Amazon WorkSpaces. This method is a cost-effective alternative for organizations that are not using services such as AWS Firewall Manager to manage and govern security groups. This article outlines the solution, and provides both an AWS CloudFormation template, and a walkthrough for manual deployment.

When a WorkSpace is created, or an instance added to an AppStream 2.0 fleet, that action is logged within AWS CloudTrail as an event. For either case, an elastic network interface is created in your AWS account for each instance. You can use a filter to detect and react to the ENI creation events. An Amazon EventBridge rule monitors the creation of a network interface and sends the action to a Lambda function. The Lambda function attaches up to five total security groups to the ENI. It uses environment variables to store which security groups to add.

This solution does not create security groups. It uses security groups that have been pre-configured and vetted within your account. It is an AWS best practice to review all settings and configurations, and also to scope policies to least privilege, before deploying.

Diagram depicting the communication flow of the services used by the solution

Time to read 15 minutes
Time to complete 1 hour
Cost to complete (estimated) $5
Learning level Expert (400)
Services used Amazon EventBridge
Amazon AppStream 2.0
Amazon WorkSpaces
AWS CloudFormation
AWS CloudTrail
AWS Identity and Access Management (IAM)
AWS Lambda

Walkthrough

In this article, you complete the following tasks:

  1. Use a CloudFormation template to deploy the required components to build the automation for attaching additional security groups to AppStream 2.0 or WorkSpaces instances.
  2. Manually create all the required components to build the automation for attaching additional security groups to AppStream 2.0 or WorkSpaces instances.
  3. Clean up resources to prevent unwanted charges on your AWS account.

Prerequisites

This article assumes that you have the following already in place:

  • An AWS account
  • Permissions to create the following service components:
    • AWS IAM roles and policies
    • AWS Lambda functions
    • Amazon EventBridge rules
  • An Amazon Virtual Private Cloud (Amazon VPC) and subnets where Amazon AppStream 2.0 or Amazon WorkSpaces will be deployed in
  • IAM security groups in the end user computing (EUC) VPC
  • (Optional) Permissions to run CloudFormation templates

Option 1: CloudFormation deployment

The provided CloudFormation template can be used to automatically deploy the components of this solution. Once deployed, you can modify various aspects to meet your needs. Because security groups are VPC-specific, this template should be run for each VPC that contains EUC resources. The CloudFormation template does not create security groups. It uses security groups that have been pre-configured and vetted within your account.

  1. Open the CloudFormation console, verify you using the Region containing your EUC resources to monitor.
  2. In the navigation pane, choose Stacks.
  3. Choose Create stack. Select With new resources (standard).
  4. Verify that the option Template is ready is selected. For Specify template, select Amazon S3 URL.
  5. For Amazon S3 URL, enter https://aws-desktopandapplicationstreaming-blog.s3.amazonaws.com/Artifacts/eucblog-200/euc_securitygroups_cloudformation.yaml.
  6. Choose Next.
  7. Enter a name for the stack and fill out the parameters:
    • Security Group ID 1 – (required) the first security group to attach to newly created instances; sg-1234567890abcdf01. These security groups must be in the same VPC as the EUC instances.
    • Security Group ID 2 – (optional) the second security group to attach to newly created instances; sg-1234567890abcdf02. These security groups must be in the same VPC as the EUC instances.
    • Security Group ID 3 – (optional) the third security group to attach to newly created instances; sg-1234567890abcdf03. These security groups must be in the same VPC as the EUC instances.
    • Security Group ID 4 – (optional) the fourth security group to attach to newly created instances; sg-1234567890abcdf04. These security groups must be in the same VPC as the EUC instances.
    • Which EUC services should this monitor – select AppStream 2.0, WorkSpaces, or Both. This will set up EventBridge triggers for the selected services.
  8. Choose Next.
  9. Optionally, add tags that will be applied to the resources deployed with the template as required by your environment.
  10. Choose Next.
  11. On the Review page, check the box I acknowledge that AWS CloudFormation might create IAM resources with custom names. Choose Create stack.

The CloudFormation template builds the resources for this solution. When finished the status will change from the CREATE_IN_PROGRESS to CREATE_COMPLETE. At this point the solution is fully deployed and will launch for new instances depending on the EUC services selected.

Option 2: Manual Deployment

The following steps describe how to create the solution manually. You create the same resources as the CloudFormation template in Option 1 using the AWS Management Console. Because security groups are VPC-specific, these steps should be replicated for each VPC that contains EUC resources.

Step 1. Create the IAM policy and role

In this step, you create an IAM policy and role that the Lambda function will assume. This provides Lambda the permissions required to read and update the security groups on network interfaces in your AWS account. The policy also contains the basic Lambda permissions required for logging. The policy created in this step should be reviewed and vetted within your environment to verify it meets your security standards prior to deployment.

  1. Open the IAM console.
  2. In the navigation pane, choose Policies.
  3. Choose Create Policy.
  4. Choose the JSON tab.
  5. Copy and paste the following JSON policy.
  6. To match your environment, replace the following values in the policy:
    • Replace aws-region-code with the AWS Region code in which the solution is being built.
    • Replace account-id-without-hyphens with the account ID number of the account in which the solution is being built.
  7. Once finished, choose Next: Tags.
  8. Add any required tags for your environment, then choose Next: Review.
  9. Enter a name for the policy, EUC_Automatic_Security_Group_Attachment_Policy.
  10. Choose Create policy.
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ec2:DescribeNetworkInterfaces",
                "ec2:ModifyNetworkInterfaceAttribute"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:aws-region-code:account-id-without-hypens:*",
            "Effect": "Allow"
        }
    ]
} 
  1. In the navigation pane, choose Roles.
  2. Select Create role.
  3. For Select type of trusted entity, verify AWS service is selected.
  4. For Use case, select Lambda, and then choose Next.
  5. For Permissions policies, browse for, or search in the filter policies search box, for the name of the policy created previously. Select the check box next to the policy name.
  6. Choose Next.
  7. Enter a name for your Role to help you identify it, EUC_Automatic_Security_Group_Attachment_Role.
  8. Choose Create role.

Step 2. Create the Lambda function

In this step, you create the Lambda function that attaches the additional security groups to network interfaces. The security groups referenced by the environment variables below should be pre-configured and vetted within your account prior to running the Lambda function.

  1. Open the Lambda console.
  2. Choose Create function.
  3. Verify Author from scratch is selected. Enter a Function name, EUC_Automatic_Security_Group_Attachment.
  4. For Runtime, select Python 3.9.
  5. Under Permissions, expand Change default execution role and select Use an existing role.
  6. For Existing role, select the IAM role created in step 1.
  7. Choose Create function.
  8. Within the Code source section, replace the placeholder code with the contents of this script.
  9. Choose Deploy to save the changes.
  10. Choose the Configuration tab.
  11. Choose Environment variables, then choose Edit.
  12. Choose Add environment variable.
  13. For Key, enter Add_SG_1.
  14. For Value enter the security group id to attach to newly created instances; for example, sg-1234567890abcdf01. This security group must be in the same VPC as the EUC instances.
  15. Repeat the above steps to create up to four total security groups to add to newly created EUC instances. For the additional variables, use key names Add_SG_2, Add_SG_3, and Add_SG_4.
  16. Choose Save.

Step 3. Create the EventBridge rule

In this final step, you create an EventBridge rule to invoke the Lambda function created in the previous step. This rule defines the criteria that matches new network interface events in CloudTrail and sends that data to Lambda.

  1. Open the EventBridge console.
  2. Choose Create rule.
  3. Enter a Name, EUC_Automatic_SG_Attachment_Trigger.
  4. Under Rule type, select Rule with an event pattern.
  5. Choose Next.
  6. Under Event source, keep AWS events or EventBridge partner events selected.
  7. Under Event pattern, choose Custom patterns (JSON editor).
  8. Paste the following JSON statement into the Event pattern box. Replace aws-region-code with the AWS Region code in which the solution is being built.
      • To trigger on WorkSpace creation:
        {
          "source": ["aws.ec2"],
          "detail": {
            "awsRegion": ["aws-region-code"],
            "responseElements": {
              "networkInterface": {
                "networkInterfaceId": [{
                  "exists": true
                }]
              }
            },
            "eventSource": ["ec2.amazonaws.com"],
            "eventName": ["CreateNetworkInterface"],
            "userIdentity": {
              "sessionContext": {
                "sessionIssuer": {
                  "userName": ["workspaces_DefaultRole"]
                }
              }
            }
          }
        }
        
      • To trigger on AppStream 2.0 instance creation:
        {
          "source": ["aws.ec2"],
          "detail": {
            "awsRegion": ["aws-region-code"],
            "responseElements": {
              "networkInterface": {
                "networkInterfaceId": [{
                  "exists": true
                }]
              }
            },
            "eventSource": ["ec2.amazonaws.com"],
            "eventName": ["CreateNetworkInterface"],
            "userIdentity": {
              "sessionContext": {
                "sessionIssuer": {
                  "userName": ["AmazonAppStreamServiceAccess"]
                }
              }
            }
          }
        }
        
      1. Choose Next.
      2. Under Target 1, select AWS service.
      3. For Select a target, select Lambda function.
      4. Then for Function, select the function created in step 2.
      5. Expand Additional settings.
      6. For Configure target input, select Matched events.
      7. Choose Next.
      8. Add any required tags for your environment, then choose Next.
      9. Choose Create rule.
      10. If you are setting up rules for both AppStream 2.0 and WorkSpaces, repeat this section to setup the event rule for each service.

Cleanup

In this blog post, you created several components that may generate costs based on usage. To avoid incurring future charges, remove the following resources.

  1. If the CloudFormation template was used, perform the following to delete all the resources used in the solution. otherwise move on to step 2.
    1. Navigate to the CloudFormation console.
    2. Select the stack created above.
    3. Choose Delete.
  2. To prevent future executions of the automation:
    1. Navigate to the EventBridge console.
    2. Choose Rules.
    3. Select the rule create above and choose Delete.
  3. Lambda functions do not incur a charge unless invoked. To remove this component completely:
    1. Open the Lambda console.
    2. Select your function.
    3. Choose Actions, then Delete.
  4. There are no charges for IAM policies and roles. To remove the IAM entities created in this article:
    1. Navigate to the IAM console.
    2. Choose Roles.
    3. Select the role created above, then choose Delete.
    4. Choose Policies.
    5. Select the policy created previously. Choose Actions, then Delete.

Conclusion

You now have a fully automated process in place to attach additional security groups to your Amazon AppStream 2.0 and Amazon WorkSpaces instances. This solution can be used to attach additional security groups required by your organization or to overcome the limits on the number of rules allowed in a single security group.

The default quota for the number of security groups you can attach to a single elastic network interface is five. The script provided in this blog is built to accommodate up to that many. It is possible to request a service quota increase to increase this limit. If you have the limit increased on your account, you can modify the provided Lambda function code and add additional environment variables to suit your needs.