aws / aws-cdk-rfcs

RFCs for the AWS CDK

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Amazon VPC Lattice L2 Construct

NetDevAutomate opened this issue · comments

Description

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

This RFC supersedes #501

Roles

Role User
Proposed by @NetDevAutomate
Author(s) @mrpackethead, @juhala-aws, @markoskandylis, @nbaillie, @GlennChia, @philipws, @nrajb, @enrique-esquivel, @sQu4rks, @taylaand
API Bar Raiser @TheRealAmazonKendra
Stakeholders @NetDevAutomate, @taylaand

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 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.

PUBLIC ISSUES

  • (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 Construct

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.

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 assosiation for a VPC:

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

const serviceNetwork = vpcLattice.ServiceNetwork.fromIdentifier('serviceNetworkId')


const serviceNetworkAssociation = new vpcLattice.ServiceNetworkAssociation(this,'someAssociation',{
  serviceNetwork: serviceNetwork,
  vpc: vpc
})

Security Groups can optionaly be supplied to the association

const serviceNetworkAssociation = new vpcLattice.ServiceNetworkAssociation(this,'someAssociation',{
  serviceNetwork: serviceNetwork,
  vpc: vpc,
  securityGroups: [securityGroup1,securityGroup2]
})

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

Defining a service nerwork

const serviceNetwork = new vpcLattice.ServiceNetwork(this,'serviceNetwork',{
  authType: "anAuthType",
  name: vpc,
})

serviceNetwork.addService(myservice)

Service network's can have an Auth Policy assigned to it. This can either be active (when the attribute authType is set to AWS_IAM) or inactive (when the attribute authType is set to None). Note that Auth policies can also be assigned to Services (detailed below).

Example Auth Policy that is active

const serviceNetwork = new vpcLattice.ServiceNetwork(this,'serviceNetwork',{
  authType: vpcLattice.LatticeAuthType.IAM,
  name: vpc,
})

const authPolicy = new iam.PolicyDocument({
  statements: [
        new iam.PolicyStatement({
          resources: ['arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0/*'],
          actions: ['vpc-lattice-svcs:Invoke'],
          effect: iam.Effect.ALLOW,
    }),
  ],
});

serviceNetwork.addAuthPolicy(authPolicy)

Example Auth Policy that is inactive. authType is by default None

const serviceNetwork = new vpcLattice.ServiceNetwork(this,'serviceNetwork',{
  name: vpc,
})

const authPolicy = new iam.PolicyDocument({
  statements: [
        new iam.PolicyStatement({
          resources: ['arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0/*'],
          actions: ['vpc-lattice-svcs:Invoke'],
          effect: iam.Effect.ALLOW,
    }),
  ],
});

serviceNetwork.addAuthPolicy(authPolicy)

Defining a service

Creates a service. A service is any software application that can run on instances containers, or serverless functions within an account or virtual private cloud (VPC).
We can add a listener to the service that will either forward to a target group or have a fixed response

const myService = new vpcLattice.VpcLatticeService(this,'myservice',{
  authType: "anAuthType",
  certificateArn: "aCertificateArn"
  customDomainName: "aCustomDomainName"
  name: "myServiceName",
})

myService.addListener(myListener)

Service's can have an Auth Policy assigned to it. This can either be active (when the attribute authType is set to AWS_IAM) or inactive (when the attribute authType is set to None). Note that Auth policies can also be assigned to Service networks.

Example Auth Policy that is active

const myService = new vpcLattice.VpcLatticeService(this,'myservice',{
  authType: vpcLattice.LatticeAuthType.IAM,
  certificateArn: "aCertificateArn"
  customDomainName: "aCustomDomainName"
  name: "myServiceName",
})

const authPolicy = new iam.PolicyDocument({
  statements: [
        new iam.PolicyStatement({
          resources: ['arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0/*'],
          actions: ['vpc-lattice-svcs:Invoke'],
          effect: iam.Effect.ALLOW,
    }),
  ],
});

myService.addAuthPolicy(authPolicy)

Defining a listener

Creates a listener for a service we must add one or more listeners to the service. On the listener we can select to either have a default action that will give us a fixed response or a default target group that will forward the trafic to the relevant target groups.

const myListener = new vpcLattice.VpcLatticeListener(this,'myListener',{
  port: "80",
  name: "myListener"
  defaultTargetGroups: [myTargetGroup1] 
})
// We can define and attach target groups to the listener
mylistener.addTargetGroups(myTargetgroup2)

// We can also create a target group with defaults set
mylistener.addTarget('target name', {
    port: 8000,
    targets: [
        instance.id
    ]
})

mylistener.addLambdaTarget(this, {
    lambda_arn: lambda.arn,
    lambda: lamba // Can be set either by passing lambda object or passing arn
})

mylistener.addALBTarget(this, {
    alb_arn: alb.arn,
    alb: alb // Can be set either by passing alb object or passing arn
})

It's possible to route traffic to targets based on conditions in the incoming HTTP request.

myListener.addTargets('example', {
  priority: 10,
  conditions: [
    vpclattice.ListenerCondition.hostHeaders(['example.com']),
    vpclattice.ListenerCondition.pathPatterns(['/ok', '/path']),
  ],
  port: 8080,
  targets: [mytarget]
});

we can add targets like above that will automate the creation of the target group and the action but we can also specify both actions if we want more control by creating the target group and action by using

myListener.addTargetsGroup('example', {
  targetgroup: myTargetGroup
});

we can define listener rules

const listenerRule = new vpclattice.ListenerRule(this, {
    listener: myListener,
    priority: 10,
    conditions: [
        vpclattice.ListenerCondition.hostHeaders(['example.com']),
        vpclattice.ListenerCondition.prefixPattern("prefix")
    ],
    action: vpclattice.ListenerAction.forward([myTargetGroup]) 
})

and then we can add the action:

myListener.addAction('example', {
  priority: 10,
  conditions: [
    vpclattice.ListenerCondition.hostHeaders(['example.com']),
  ],
  action: vpclattice.ListenerAction.fixedResponse(200, {
    contentType: 'text/plain',
    messageBody: 'OK',
  })
});

Defining 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.

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

Adding a VPC Lattice Service to Service Network

myNetwork.associateService(
  dnsEntry: {
    domainName: 'domainName',
    hostedZoneId: 'hostedZoneId',
  },
  service: myService
);

Associate a VPC to Service Network

myNetwork.associateVPC(
  vpc: myVPC,
  securityGroupIDs: [mySecurityGroup], 
);

Target Groups

A Target Group is a collection of targets, or compute resources that run your application or service. Targets in VPC Lattice can be EC2 instances, IP addresses, Lambda functions, Application Load Balancers, or Kubernetes Pods.

const healthCheckConfig = new vpclattice.HealthCheck({
    enabled: True,
    healthCheckIntervalSeconds: 20,
})

const targetGroup = new vpclattice.TargetGroup(this, {
    name: "Name",
    type: vpclattice.TargetType.INSTANCE,
    ipAddressType: vpclattice.IpAddressType.IPV4,
    vpcIdentifier: vpc.id,
    protocolVersion: vpclattice.ProtocolVersion.HTTP2,
    port: 8080,
    protocol: vpclattice.Protocol.HTTP,
    healthCheck: healthCheckConfig,
})

// You can also use target type specific constructs that have defaults set
const lambdaTarget = new vpclattice.LambdaTarget()
cosnt albTarget = new vpclattice.ALBTarget()

Auth policies

Auth policies are attached to service or service networks to control whether a specified principal has access to a group of services or specific service. You can attach one auth policy to each service network or service that you want to control access to. Since Auth policies must be associated to a service or service network, we cannot create a standalone resource for it (this differs from IAM policies which can be standalone). Instead we must use an addAuthPolicy method on the Service or Service Network. This method reference the service or service network ID this.serviceId or this.serviceNetworkId. The function takes in the policy parameter which defines the actions, resources, principals and conditions, like an IAM policy.

const authPolicy = new iam.PolicyDocument({
  statements: [
        new iam.PolicyStatement({
          resources: ['arn:aws:vpc-lattice:us-west-2:123456789012:service/svc-0123456789abcdef0/*'],
          actions: ['vpc-lattice-svcs:Invoke'],
          effect: iam.Effect.ALLOW,
    }),
  ],
});

Public FAQ

What are we launching today?

Amazon VPC Lattice AWS CDK L2 Construct

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

What is the technical solution (design) of this feature?

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`

Closing this ticket as it is not a core library concern and we do not have bandwidth to collaborate on implementation. We believe the functionality is beneficial, but does not intersect with the core framework and should be vended and maintained separately.