-
Notifications
You must be signed in to change notification settings - Fork 0
Added BackendDefaults to Virtual Node #3
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
base: master
Are you sure you want to change the base?
Changes from 8 commits
5326284
e476ae7
dbc5870
5b4c97b
b4b7f95
ce35692
4aea038
25208a4
5b260be
a55a305
7ca64da
01be91b
7e2ddbc
49824b1
0306a36
045d2a7
2cad882
20c0e96
d36fc42
4e07587
da25261
41d2c12
d18fdc4
4ec4b21
8b0b863
bd2d85e
8b707ce
de939c3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| import * as cdk from '@aws-cdk/core'; | ||
| import { CfnVirtualNode } from './appmesh.generated'; | ||
|
|
||
| /** | ||
| * Defines the TLS validation context trust. | ||
| */ | ||
| export abstract class TLSClientValidation { | ||
| /** | ||
| * TLS validation context trust for a local file | ||
|
||
| */ | ||
| public static fileTrust(props: FileTrustOptions): TLSClientValidation { | ||
| return new FileTrust(props); | ||
| } | ||
|
|
||
| /** | ||
| * TLS validation context trust for ACM Private Certificate Authority (CA). | ||
| */ | ||
| public static acmTrust(props: ACMTrustOptions): TLSClientValidation { | ||
| return new ACMTrust(props); | ||
| } | ||
|
|
||
| /** | ||
| * Returns Trust context based on trust type. | ||
| */ | ||
| public abstract bind(scope: cdk.Construct): TLSValidationConfig; | ||
| } | ||
| /** | ||
| * Represents a Transport Layer Security (TLS) validation context trust for a local file | ||
| */ | ||
| class FileTrust extends TLSClientValidation { | ||
| /** | ||
| * Path to the Certificate Chain file on the file system where the Envoy is deployed. | ||
| */ | ||
| readonly certificateChain: string; | ||
|
|
||
| constructor(props: FileTrustOptions) { | ||
| super(); | ||
| this.certificateChain = props.certificateChain; | ||
| } | ||
|
|
||
| public bind(_scope: cdk.Construct): TLSValidationConfig { | ||
| return { | ||
| tlsValidation: { | ||
| trust: { | ||
| file: { | ||
| certificateChain: this.certificateChain, | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Represents a TLS validation context trust for an AWS Certicate Manager (ACM) certificate. | ||
| */ | ||
| class ACMTrust extends TLSClientValidation { | ||
| /** | ||
| * Amazon Resource Name of the Certificates | ||
| */ | ||
| readonly certificateAuthorityArns: string[]; | ||
|
|
||
| constructor(props: ACMTrustOptions) { | ||
| super(); | ||
| this.certificateAuthorityArns = props.certificateAuthorityArns; | ||
| } | ||
|
|
||
| public bind(_scope: cdk.Construct): TLSValidationConfig { | ||
| return { | ||
| tlsValidation: { | ||
| trust: { | ||
| acm: { | ||
| certificateAuthorityArns: this.certificateAuthorityArns, | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Properties of TLS validation context | ||
| */ | ||
| export interface TLSValidationConfig { | ||
| /** | ||
| * Represents single validation context property | ||
| */ | ||
| readonly tlsValidation: CfnVirtualNode.TlsValidationContextProperty; | ||
| } | ||
|
|
||
| /** | ||
| * Default configuration that is applied to all backends for the virtual node. | ||
| * Any configuration defined will be overwritten by configurations specified for a particular backend. | ||
| */ | ||
| export interface ClientPolicy { | ||
| /** | ||
| * Client policy for TLS | ||
| */ | ||
| readonly tlsClientPolicy: TLSClientPolicyOptions; | ||
| } | ||
|
|
||
| /** | ||
| * TLS Connections with downstream server will always be enforced if True | ||
| */ | ||
| export interface TLSClientPolicyOptions { | ||
| /** | ||
| * TLS enforced if True. | ||
| * | ||
| * @default - True | ||
| */ | ||
| readonly enforce?: boolean; | ||
|
|
||
| /** | ||
| * TLS enforced on these ports. If not specified it is enforced on all ports. | ||
| * | ||
| * @default - none | ||
| */ | ||
| readonly ports?: number[]; | ||
|
|
||
| /** | ||
| * Policy used to determine if the TLS certificate the server presents is accepted | ||
| * | ||
| * @default - none | ||
| */ | ||
| readonly validation: TLSClientValidation; | ||
| } | ||
|
|
||
| /** | ||
| * ACM Trust Properties | ||
| */ | ||
| export interface ACMTrustOptions { | ||
| /** | ||
| * Amazon Resource Names (ARN) of trusted ACM Private Certificate Authorities | ||
| */ | ||
| readonly certificateAuthorityArns: string[]; | ||
| } | ||
|
|
||
| /** | ||
| * File Trust Properties | ||
| */ | ||
| export interface FileTrustOptions { | ||
| /** | ||
| * Path to the Certificate Chain file on the file system where the Envoy is deployed. | ||
| */ | ||
| readonly certificateChain: string; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import { Construct } from 'constructs'; | |
| import { CfnVirtualNode } from './appmesh.generated'; | ||
| import { IMesh, Mesh } from './mesh'; | ||
| import { AccessLog } from './shared-interfaces'; | ||
| import { ClientPolicy } from './validation-context'; | ||
| import { VirtualNodeListener, VirtualNodeListenerConfig } from './virtual-node-listener'; | ||
| import { IVirtualService } from './virtual-service'; | ||
|
|
||
|
|
@@ -94,6 +95,13 @@ export interface VirtualNodeBaseProps { | |
| * @default - No access logging | ||
| */ | ||
| readonly accessLog?: AccessLog; | ||
|
|
||
| /** | ||
| * Default Configuration Virtual Node uses to communicate with Vritual Service | ||
|
||
| * | ||
| * @default - No Config | ||
| */ | ||
| readonly backendDefaults?: ClientPolicy; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -175,6 +183,7 @@ export class VirtualNode extends VirtualNodeBase { | |
| */ | ||
| public readonly mesh: IMesh; | ||
|
|
||
| private readonly backendDefaults = new Array<CfnVirtualNode.BackendDefaultsProperty>(); | ||
|
||
| private readonly backends = new Array<CfnVirtualNode.BackendProperty>(); | ||
| private readonly listeners = new Array<VirtualNodeListenerConfig>(); | ||
|
|
||
|
|
@@ -187,6 +196,9 @@ export class VirtualNode extends VirtualNodeBase { | |
|
|
||
| props.backends?.forEach(backend => this.addBackend(backend)); | ||
| props.listeners?.forEach(listener => this.addListener(listener)); | ||
| if (props.backendDefaults) { | ||
| this.addBackendDefaults(props.backendDefaults); | ||
| } | ||
| const accessLogging = props.accessLog?.bind(this); | ||
|
|
||
| const node = new CfnVirtualNode(this, 'Resource', { | ||
|
|
@@ -195,6 +207,7 @@ export class VirtualNode extends VirtualNodeBase { | |
| spec: { | ||
| backends: cdk.Lazy.anyValue({ produce: () => this.backends }, { omitEmptyArray: true }), | ||
| listeners: cdk.Lazy.anyValue({ produce: () => this.listeners.map(listener => listener.listener) }, { omitEmptyArray: true }), | ||
| backendDefaults: cdk.Lazy.anyValue({ produce: () => this.backendDefaults[0] }, { omitEmptyArray: true }), | ||
| serviceDiscovery: { | ||
| dns: props.dnsHostName !== undefined ? { hostname: props.dnsHostName } : undefined, | ||
| awsCloudMap: props.cloudMapService !== undefined ? { | ||
|
|
@@ -216,6 +229,24 @@ export class VirtualNode extends VirtualNodeBase { | |
| resourceName: this.physicalName, | ||
| }); | ||
| } | ||
| /** | ||
| * Adds Default Backend Configuration for virtual node to communicate with Virtual Services. | ||
| */ | ||
| public addBackendDefaults(clientPolicy: ClientPolicy) { | ||
|
||
| if (this.backendDefaults.length === 0) { | ||
| this.backendDefaults.push({ | ||
| clientPolicy: { | ||
| tls: { | ||
| enforce: clientPolicy.tlsClientPolicy.enforce ?? true, | ||
|
||
| validation: clientPolicy.tlsClientPolicy.validation.bind(this).tlsValidation, | ||
| ports: clientPolicy.tlsClientPolicy.ports, | ||
| }, | ||
| }, | ||
| }); | ||
| } else { | ||
| throw new Error('Virtual Node can have only one backend default'); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Utility method to add an inbound listener for this VirtualNode | ||
|
|
@@ -231,11 +262,19 @@ export class VirtualNode extends VirtualNodeBase { | |
| this.backends.push({ | ||
| virtualService: { | ||
| virtualServiceName: virtualService.virtualServiceName, | ||
| clientPolicy: virtualService.clientPolicy ? { | ||
| tls: { | ||
| enforce: virtualService.clientPolicy?.tlsClientPolicy.enforce ?? true, | ||
| validation: virtualService.clientPolicy?.tlsClientPolicy.validation.bind(this).tlsValidation, | ||
| ports: virtualService.clientPolicy?.tlsClientPolicy.ports, | ||
| }, | ||
| } : undefined, | ||
| }, | ||
| }); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| function renderAttributes(attrs?: {[key: string]: string}) { | ||
| if (attrs === undefined) { return undefined; } | ||
| return Object.entries(attrs).map(([key, value]) => ({ key, value })); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backend Client Policies won't be the only shapes that support validation contexts. Listeners could support validation contexts in the future (ex. mTLS).
Unless there is a limitation that forces us to have 2 different shapes for client validation and server validation, I'd recommend changing the name here to a more general
TLSValidationContext. And creating a separate file for client policy shapes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point. I have updated the PR.