Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Amazon VPC Lattice L2 Construct #631

Open
1 of 11 tasks
clopca opened this issue Aug 14, 2024 · 0 comments
Open
1 of 11 tasks

Amazon VPC Lattice L2 Construct #631

clopca opened this issue Aug 14, 2024 · 0 comments
Labels
status/proposed Newly proposed RFC

Comments

@clopca
Copy link

clopca commented Aug 14, 2024

Description

This RFC proposes a new L2 module for CDK to support AWS VPC Lattice.

This RFC supercedes #502

Roles

Role User
Proposed by @clopca
Author(s) @clopca, @aws-rafams
API Bar Raiser @TheRealAmazonKendra
Stakeholders @TBD

See RFC Process for details

Workflow

  • Tracking issue created (label: status/proposed)
  • API bar raiser assigned (ping us at #aws-cdk-rfcs if needed)
  • Kick off meeting
  • RFC pull request submitted (label: status/review)
  • Community reach out (via Slack and/or Twitter)
  • API signed-off (label status/api-approved applied to pull request)
  • Final comments period (label: status/final-comments-period)
  • Approved and merged (label: status/approved)
  • Execution plan submitted (label: status/planning)
  • Plan approved and merged (label: status/implementing)
  • Implementation complete (label: status/done)

Author is responsible to progress the RFC according to this checklist, and
apply the relevant labels to this issue so that the RFC table in README gets
updated.

(vpclattice): L2 for Amazon VPC Lattice #25452

USER STORIES

As Any User I would like to:

  • Have a intuitive, low code user experience
  • Abstract the unerlying complexities to allow different personas to use the same CDK Construct to deploy and manage aspects of the Amazon VPC Lattice configuration
  • Integration between this construct and other CDK constructs
  • Apply secure, best practice configurations as default

As a Service Owner I would like to:

  • Publish my service for others to access
  • Control Authentication and Authorisation for my services
  • Control load distribution across my compute resources
  • Hide the implementation detail of my services from consumers

As a Service Consumer I would like to:

  • Be able have my resources use services that are available to me in my VPCs
  • Authenticate with services
  • Restrict access for services to security groups that I decide

As a Platform/Network Admin I would like to:

  • Create Service Networks for Owners and Consumers to use

README

VpcLattice Constructs

  • Service: An independently deployable unit of software that delivers a specific task or function. A service can run on EC2 instances or ECS containers, or as Lambda functions, within an account or a virtual private cloud (VPC). A VPC Lattice service has the following components: target groups, listeners, and rules.
  • Target Group: A collection of resources, also known as targets, that run your application or service. Targets can be EC2 instances, IP addresses, Lambda functions, Application Load Balancers, or Kubernetes Pods. These are similar to the target groups provided by Elastic Load Balancing, but they are not interchangeable. A target group can be associated with a listener, and the listener can route requests to the targets in the target group.
  • Listener: A process that checks for connection requests, and routes them to targets in a target group. A service can have up to two listeners, using the HTTP and HTTPS protocols and port numbers from 1 to 65535.
  • Rule: A default component of a listener that forwards requests to the targets in a VPC Lattice target group. Each rule consists of a priority, one or more actions, and one or more conditions. Rules determines how the listener routes client requests.
  • Service Network: A logical boundary for a collection of services. A client is any resource deployed in a VPC that is associated with the service network. To communicate with services in a certain service network, clients and other services must be associated with the same service network. They must also be authenticated and authorized by the service network or the specific service for this communication to take place.
  • ServiceNetwork Service Association: A Service association is a relationship between a Service and a Service Network. When you associate a Service with a Service Network, it enables all the targets within that Service to be clients and communicate with other services associated to that same Service Network.
  • ServiceNetwork VPC Association: A VPC association is a relationship between a VPC and a service network. When you associate a VPC with a service network, it enables all the targets within that VPC to be clients and communicate with other services associated to that same service network.
  • Auth Policy: Fine-grained authorization policies that can be used to define access to services. You can attach separate auth policies to individual services or to the service network. For example, you can create a policy for how a payment service running on an auto scaling group of EC2 instances should interact with a billing service running in AWS Lambda.
  • AccessLogSubscription: Enables access logs to be sent to Amazon CloudWatch, Amazon S3, and Amazon Kinesis Data Firehose. The service network owner can use the access logs to audit the services in the network. The service network owner can only see access logs from clients and services that are associated with their service network. Access log entries represent traffic originated from VPCs associated with that network. For more information, see Access logs in the Amazon VPC Lattice User Guide.

Service

In VPC Lattice, we refer to a microservice as a service. It represents an independently deployable unit of software that delivers a specific task or function.

To create a service, use the Service Construct:

const logBucket = new Bucket(stack, 'LogsBucket', {});

new Service(stack, 'Service', {
  authType: vpclattice.AuthType.AWS_IAM,
  name: 'my-custom-name',
  removalPolicy: cdk.RemovalPolicy.DESTROY,
  loggingDestinations: [vpclattice.LoggingDestination.s3(logBucket)],
});

Service access

Access settings enable you to configure and manage client access to a service.
Access settings include auth type and auth policies. Auth policies help you authenticate and authorize traffic flowing to services within VPC Lattice.

You can apply auth policies at the service network level, the service level, or both. At the service level, service owners can apply fine-grained controls, which can be more restrictive.

  • You can chooose to not define an auth policy:
const testSvc = new Service(stack, 'Parking', {
  ...
  authType: AuthType.NONE,
  ...
});
  • You can chooose a predefined policy template:
const testSvc = new Service(stack, 'Parking', {
  ...
  authType: AuthType.AWS_IAM,
  authPolicy: AuthPolicyDocument.UNAUTHENTICATED,
  ...
});
  • You can create a custom auth policy document using higher level statements:
const testSvc = new Service(stack, 'Parking', {
  ...
  authType: AuthType.AWS_IAM,
  authPolicy: new AuthPolicyDocument({
      statements: [
        AuthPolicyStatement.allowOnlyRole(...)
        AuthPolicyStatement.allowOnlyOrganization(...)
      ]
  }),
  ...
});
  • You can create a custom auth policy document using low level statements:
const testSvc = new Service(stack, 'Parking', {
  ...
  authType: AuthType.AWS_IAM,
  authPolicy: new AuthPolicyDocument({
    statements: [
      new PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: ['vpc-lattice-svcs:*'],
        resources: ['*'],
        principals: [new iam.StarPrincipal()],
        conditions: {
          StringEquals: { 'vpc-lattice-svcs:RequestMethod': 'GET' },
        },
      }),
    ]
  }),
  ...
});

Target Groups

A VPC Lattice target group is a collection of targets, or compute resources, that run your application. Targets can be EC2 instances, IP addresses, Lambda functions, Application Load Balancers, or Kubernetes Pods. To register an EKS pod as a target, use the AWS Gateway API Controller, which gets the IP addresses from the Kubernetes service.

To create a target group use the appropriate construct according to the target type.

Lambda Function

const lambdaFunction = new LambdaFunction(stack, 'LambdaTargetFunction', {
  runtime: Runtime.NODEJS_18_X,
  code: Code.fromInline(`
        exports.handler = async (event) => {
            return {
                isBase64Encoded: false,
                statusCode: 200,
                body: JSON.stringify({ message: "Hello from Lambda!" }),
            };
        };
    `),
  handler: 'index.handler',
});

const tg1 = new LambdaTargetGroup(stack, 'LambdaTG', {
  name: 'lambda-tg1',
  target: lambdaFunction,
});

Application Load Balancer

const albSvc = new ApplicationLoadBalancedFargateService(stack, 'Service', {
  vpc,
  memoryLimitMiB: 1024,
  cpu: 512,
  taskImageOptions: {
    image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'),
    containerPort: 80,
  },
  publicLoadBalancer: false,
});

new AlbTargetGroup(stack, 'ALBTG', {
  vpc,
  loadBalancer: albSvc.loadBalancer,
});

IP Targets

const instance1 = new Instance(stack, 'Instance1', {
  vpc,
  instanceType: cdk.aws_ec2.InstanceType.of(cdk.aws_ec2.InstanceClass.T3, cdk.aws_ec2.InstanceSize.SMALL),
  machineImage: cdk.aws_ec2.MachineImage.latestAmazonLinux2(),
});

const instance2 = new Instance(stack, 'Instance2', {
  vpc,
  instanceType: cdk.aws_ec2.InstanceType.of(cdk.aws_ec2.InstanceClass.T3, cdk.aws_ec2.InstanceSize.SMALL),
  machineImage: cdk.aws_ec2.MachineImage.latestAmazonLinux2(),
});

const tg1 = new IpTargetGroup(stack, 'IpTG', {
  name: 'ip-tg1',
  vpc,
  targets: [
    {
      ipAddress: instance1.instancePrivateIp,
      port: 80,
    },
  ],
});

tg1.addTarget({
  ipAddress: instance2.instancePrivateIp,
  port: 80,
});

Instance

const instance1 = new Instance(stack, 'Instance1', {
  vpc,
  instanceType: cdk.aws_ec2.InstanceType.of(cdk.aws_ec2.InstanceClass.T3, cdk.aws_ec2.InstanceSize.SMALL),
  machineImage: cdk.aws_ec2.MachineImage.latestAmazonLinux2(),
});

const instance2 = new Instance(stack, 'Instance2', {
  vpc,
  instanceType: cdk.aws_ec2.InstanceType.of(cdk.aws_ec2.InstanceClass.T3, cdk.aws_ec2.InstanceSize.SMALL),
  machineImage: cdk.aws_ec2.MachineImage.latestAmazonLinux2(),
});

const tg1 = new InstanceTargetGroup(stack, 'Ec2TG', {
  vpc,
  instances: [
    {
      instance: instance1,
      port: 80,
    },
  ],
  healthCheck: {
    enabled: false,
    protocol: HealthCheckProtocol.HTTP,
    path: '/health',
    port: 8080,
  },
});

Auto-scaling Group

const asg = new AutoScalingGroup(stack, 'ASG', {
  vpc,
  instanceType: cdk.aws_ec2.InstanceType.of(cdk.aws_ec2.InstanceClass.T2, cdk.aws_ec2.InstanceSize.MICRO),
  machineImage: cdk.aws_ec2.MachineImage.latestAmazonLinux2(),
});

const tg1 = new InstanceTargetGroup(stack, 'ASG-TG', {
  vpc,
  autoScalingGroups: [asg],
  healthCheck: {
    enabled: false,
    protocol: HealthCheckProtocol.HTTP,
    path: '/health',
    port: 8080,
  },
});

Service Network

Creates a service network. A service network is a logical boundary for a collection of services. You can associate services and VPCs with a service network. To communicate with services in a certain service network, clients and other services must be associated with the same service network. They must also be authenticated and authorized by the service network or the specific service for this communication to take place.
To create a service network use the ServiceNetwork construct.

const myNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
  authType: vpclattice.AuthType.AWS_IAM,
});

Service Network Access

Access settings enable you to control access to a service network. You can define an auth policy for the service network, which can either be active (when the attribute authType is set to AWS_IAM) or inactive (when the attribute authType is set to NONE). It works in the same way as the auth policy for a service.

const myNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
  authType: vpclattice.AuthType.AWS_IAM,
  authPolicy: AuthPolicyDocument.UNAUTHENTICATED,
  ...
});

Service Network VPC associations

When you associate a VPC with a service network, it enables all the targets within that VPC to be clients and communicate with other services associated to that same service network.

You can optional make use of Security Groups to control the access of the VPC association, allowing some traffic segmentation before the traffic arrives to the Service Network.

Basic Use

Creating a new service network association for a VPC:

const vpc = new ec2.vpc(this,'myVpc',{
})

const serviceNetwork = vpcLattice.ServiceNetwork.fromId('serviceNetworkId')
serviceNetwork.associateVPC(vpc)

We can also create a new service network association for a VPC:

const vpc = new ec2.vpc(this,'myVpc',{})

const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
  authType: vpclattice.AuthType.AWS_IAM,
  vpcAssociations: [{ vpc: vpc, }]
});

Security Groups can optionally be supplied to the association

const vpc = new ec2.vpc(this,'myVpc',{})

const securityGroup = new ec2.SecurityGroup(this,'mySecurityGroup',{
    vpc: vpc
  })

const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
  authType: vpclattice.AuthType.AWS_IAM,
  vpcAssociations: [{ vpc: vpc, securityGroups: [securityGroup] }]
});

You can create more than 1 VPC association per Service Network and more than 1 Service Network per VPC.

Adding a VPC Lattice Service to Service Network

There are three ways to associate a service to a service network:

  1. Add the Service to the Service Network
  2. Add the Service Network to the Service
  3. Create a Service Network Service Association

Add the Service to the Service Network

Through the Service Network Properties

The Service Network can be created with the Service already associated to it. This is the simplest way to create a Service Network with a Service.

const service = new vpclattice.Service(this, 'myService', {
  name: 'myService',
});

const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
  authType: vpclattice.AuthType.AWS_IAM,
  services: [service],
});

Through the associateService method

The Service can be created and then associated to the Service Network later.

const service = new vpclattice.Service(this, 'myService', {
  name: 'myService',
});

const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
});
serviceNetwork.associateService(service)

Add the Service Network to the Service

Through the Service Properties

The Service can be created with the Service Network already associated to it. This is the simplest way to create a Service with a Service Network.

const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
});

const service = new vpclattice.Service(this, 'myService', {
  name: 'myService',
  serviceNetwork: serviceNetwork,
});

Through the associateWithServiceNetwork method

The Service can be created and then associated to the Service Network later.

  const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
    name: 'myNetwork',
  });

const service = new vpclattice.Service(this, 'myService', {
  name: 'myService',
});

serviceNetwork.associateService(service)

Create a Service Network Service Association

This method allows to create a Service Network Service Association directly.

const serviceNetwork = new vpclattice.ServiceNetwork(this, 'myNetwork', {
  name: 'myNetwork',
  authType: vpclattice.AuthType.AWS_IAM,
});

const service = new vpclattice.Service(this, 'myService', {
  name: 'myService',
});

const serviceNetworkServiceAssociation = new vpclattice.ServiceNetworkServiceAssociation(this, 'myServiceNetworkServiceAssociation', {
  serviceNetwork: serviceNetwork,
  service: service,
});

Public FAQ

What are we launching today?

We are launching the VPC Lattice construct in the CDK. This construct will allow users to deploy and manage VPC Lattice resources in their CDK stack.

Why should I use this construct?

This CDK L2 Construct can be used to deploy resources from Amazon VPC Lattice. VPC Lattice is a fully managed application networking service that you use to connect, secure, and monitor all your services across multiple accounts and virtual private clouds (VPCs).

This construct handles all the different resources you can use with VPC Lattice: Service Network, Service, Listeners, Listener Rules, Target Groups (and targets), and Associations (Service or VPC). You have the freedom to create the combination of resources you need, so in multi-AWS Account environments you can make use of the module as many times as needed (different providers) to create your application network architecture.

You can check common Amazon VPC Lattice Reference Architectures to understand the different use cases you can build with the AWS service.

  • It simplifies the deployment of common patterns for AWS VPC Lattice
  • It has been tested and implemented as part of a number of wider architectures
  • It is extensible to support other patterns as they emerge
  • It simplifies AWS VPC Lattice adoption and administration
  • Allows you to integrate infrastructure deployment with your application code
  • Reduces time to deploy and test AWS VPC Lattice
  • Provides separation of concerns with a common interface for user personas

Internal FAQ

Why are we doing this?

  • To provide a CDK native interface for AWS VPC Lattice
  • Provide a way to deploy AWS VPC Lattice deterministically

Why should we not do this?

  • AWS Lattice is relatively new and has not yet had much time to develop its uses cases
  • L1s exist that can do the job, (but are more work for developers and more code to maintain)
  • This Module will need to be maintained over time, and extended as features evolve

Is this a breaking change?

  • No we aim to be compatible, and this is the first iteration of this module.

What are the drawbacks of this solution?

  • It is an opinionated pattern, however there are escapes to help customisation where needed.
  • It is a new AWS Service and its common usecases and features may change and evolve

Ticking the box below indicates that the public API of this RFC has been signed-off by the API bar raiser (the api-approved label was applied to the RFC pull request):

[ ] Signed-off by API Bar Raiser @xxxxx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/proposed Newly proposed RFC
Projects
None yet
Development

No branches or pull requests

1 participant