x-elbv2

x-elbv2:
  lbA:
    Properties: {}
    MacroParameters: {}
    Listeners: []
    TargetGroups: {}
    Services: []
    DnsAliases: []
    Settings: {}

Create new ELBv2 (ALB/NLB) and configure traffic to send to the services. You can define conditions to distinguish services from each other and allow to re-use the same ELBv2 (mostly applies to ALBs) to use it as a smart reverse proxy.

Hint

Supports OIDC and Cognito Conditions. Refer to x-cognito_userpool for more details.

Properties

For this particular resource, the only attributes that match the CFN definition that ECS Compose-X will import are

All other settings are automatically generated for you based on the network and security definitions you have defined in the services and targets section.

Subnets associations can be overridden in the Settings.Subnets section. See Subnets for more details.

Hint

For Application Load Balancers, a new security group will be created automatically. Subnets are selected automatically based on the scheme you indicated. If selected a public NLB, the EIP addressed will automatically be provisioned too.

DnsAliases

To create DNS records in Route53 pointing to your ELBv2, see Use with x-elbv2

MacroParameters

ELBv2 Macro Parameters
timeout_seconds: int
desync_mitigation_mode: str
drop_invalid_header_fields: bool
http2: bool
cross_zone: bool
Ingress: {}

Attributes shortcuts

These settings are just a shorter notation for the LB Attributes

Shorthand

AttributeName

LB Type

timeout_seconds

idle_timeout.timeout_seconds

ALB

desync_mitigation_mode

routing.http.desync_mitigation_mode

ALB

drop_invalid_header_fields

routing.http.drop_invalid_header_fields.enabled

ALB

http2

routing.http2.enabled

ALB

cross_zone

load_balancing.cross_zone.enabled

NLB

Ingress

Similar syntax as for ECS Services Ingress, allow you to define Ingress. See the Ingress JSON Schema definition .

Tip

When using NLB, ingress must be defined at the service level, as NLB do not have a SecurityGroup

Ingress Syntax
Ingress:
  ExtSources: []
  AwsSources: []
ExtSources syntax
ExtSources:
  - Name: str (if any non alphanumeric character set, will be deleted)
    Description: str
    IPv4: str
AwsSources syntax
AwsSources:
  - Type: SecurityGroup|PrefixList (str)
    Id: sg-[a-z0-9]+|pl-[a-z0-9]+
    Lookup: {}

Tip

You can use either Id or Lookup to identify the SecurityGroups. Check out the Lookup syntax reference

Listeners

You can define in a very simple way your Listener definition and cross-reference other resources, here, the services and ACM certificates you might be creating.

It has its own set of properties, custom to ECS ComposeX.

The following properties are identical to the original CFN definition.

JSON Schema definition

Hint

For certificates, you can also use x-acm to refer to an ACM certificate you are creating with this stack. It will automatically import the Certificate ARN and map it once created.

Hint

You can re-use the same ACM certificate defined in x-acm for multiple listeners. Make sure to have all the Alt. Subjects you need!

Warning

The certificate ARN must be valid when set, however, we are not checking that it actually exists.(yet)

Listener Targets

List of targets to send the requests to. These are equivalent to ELBv2::TargetGroup

name: <service_name> ie. app03:app03
access: <domain name and or path> ie. domain.net/path
cognito_auth: AuthenticateCognitoConfig

This represents the targets and simultaneously the Listener Rules to apply so that you can point to multiple services at once and implement these rules.

name

The name of the family and service in that family to send the requests to.

access

Allows you to define the conditions based on the path or domain name (or combination of both) that should be in place to forward requests.

If you only define the domain name, any path in that domain will be what’s matched.

AuthenticateCognitoConfig

Defines the AuthenticateCognitoConfig requirement condition / action.

AuthenticateOidcConfig

Similar to AuthenticateCognitoConfig but for OIDC providers. This allows to respect all the AuthenticateOidcConfig Properties as per CFN definition.

Tip

We highly recommend that you store the OIDC details into a secret in secrets manager!

Hint

For both AuthenticateCognitoConfig and AuthenticateOidcConfig, the rules defined in access will be set to come after the authenticate action.

TargetGroups

Added in 0.23.16+

This allows you to create singular Target Groups, in the similar way to Services . The differences are, with Services_ :

  • you are creating 1 Target Group per family:container:port combination

  • you cannot have more than one service in ECS registering to that Target Group.

We’ve tried to make the syntax friendlier than with Services Let’s take the below example, where we have 3 services, placed logically in different zones. We still want these services to have the same NLB route the traffic to each of them. For that, we define a target group, for example, all-gateways . The name is totally arbitrary, but must be unique.

We then simply list the services that we want to attach/assign to that target group. We give the family:container combination, and then which port from that combination should be used to send traffic to.

Apart from that, the attributes set within a target group are the same as the CFN Target Group Attributes

x-elbv2:
  internal-ingress:
    TargetGroups:
      all-gateways:
        Port: 6969
        Protocol: TCP
        HealthCheck:
          HealthCheckIntervalSeconds: 17
          HealthCheckProtocol: TCP
          HealthCheckTimeoutSeconds: 10
          HealthyThresholdCount: 2
          UnhealthyThresholdCount: 2
        TargetGroupAttributes:
          deregistration_delay.timeout_seconds: "30"
          proxy_protocol_v2.enabled: "false"
          preserve_client_ip.enabled: "false"
        Services:
          - Name: proxy-internal-az3:conduktor-proxy-internal-az3
            Port: 6969
          - Name: proxy-internal-az2:conduktor-proxy-internal-az2
            Port: 6969
          - Name: proxy-internal-az1:conduktor-proxy-internal-az1
            Port: 6969

Tip

Because of of the HealthCheck port, we recommend to use the same port on each container.

Hint

ECS Compose-X will still try to automatically fix the properties of your target group just as it did before.

Services

This follows the regular pattern of having the name of the service and access, only this time in a slightly different format. The services represent the Target Group definition of your service. Once again, in an attempt to keep things simple, you do not have to indicate all of the settings exactly as CFN does.

The Targets will automatically be pointing towards the ECS Service tasks.

Syntax

name: <family name:container name>
protocol: <str>
port : <int>
healthcheck: <str>
TargetGroupAttributes: list|map

JSON Schema definition

name

Given that you can now re-use one of the service in the docker-compose file multiple times for multiple ECS Services in multiple Task definitions, and ECS to ELBv2 supports to route traffic to a specific container in the task definition, you have to indicate the service name in the following format

# name: <family_name>:<service_name>
name: youtoo:app01
name: app03:app03

Hint

If you service is not associated to a family via deploy labels, the family name is the same as the service name.

protocol

The Target Group protocol

port

The port of the target to send the traffic to

Hint

This port is the port used by the Target Group to send traffic to, which can be different to your healthcheck port.

healthcheck

shorthand regular expression
x-elbv2:
  lb:
    Services:
      - healthcheck: (port:protocol)(:healthy_count:unhealthy_count:intervals:timeout)?(:path:http_codes)?
full definition with the properties
x-elbv2:
  Services:
    - name: family:service
      healthcheck:
        HealthCheckEnabled:
        HealthCheckIntervalSeconds:
        HealthCheckPath:
        HealthCheckPort:
        HealthCheckProtocol:
        HealthCheckTimeoutSeconds:
        HealthyThresholdCount:
        UnhealthyThresholdCount:
        Matcher : <Matcher>

The healthcheck can be defined either as a string, will set the properties values accordingly, or as a mapping, using the same healthcheck as the ones defined in Target Group definition.

Tip

ECS Compose-X will log a warning when it detects an invalid value, and corrects it to the valid one.

TargetGroupAttributes

In order to set Target Group specific settings, you can use CFN TargetGroupAttributes properties.

In AWS CFN, it is a list of Key/Value objects, so compose-x supports it that way.

Services:
  - name: app03:app03
    port: 5000
    healthcheck: 5000:TCP:7:2:15:5
    protocol: TCP
    TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: "30"
      - Key: proxy_protocol_v2.enabled
        Value: "true"
      - Key: preserve_client_ip.enabled
        Value: "true"

But in order to avoid duplicates and make the merge of compose files easier, you can also defined these properties into a map/dict structure and compose-x will automatically convert it to the CFN Expected format.

Services:
  - name: app03:app03
    port: 5000
    healthcheck: 5000:TCP:7:2:15:5
    protocol: TCP
    TargetGroupAttributes:
      deregistration_delay.timeout_seconds: "30"
      proxy_protocol_v2.enabled: "true"
      preserve_client_ip.enabled: "true"

Hint

Compose-X will, based on the type of Load Balancer, ensure that the properties you set are compatible with the LoadBalancer type and the values are valid / in range.

Property Name

LB Type

Allowed Values

deregistration_delay.timeout_seconds

ALL

Range(0,3600) Seconds

stickiness.enabled

  • ALB

  • NLB

  • “true”

  • “false”

stickiness.type

  • ALB

  • NLB

ALB:
  • lb_cookie

  • app_cookie

NLB:
  • source_ip

load_balancing.algorithm.type

  • ALB

  • round_robin

  • least_outstanding_requests

slow_start.duration_seconds

  • ALB

Range(30-900) Seconds

stickiness.app_cookie.cookie_name

  • ALB

String Cannot use or start with * AWSALB * AWSALBAPP * AWSALBTG

stickiness.app_cookie.duration_seconds

  • ALB

Range(1,604800) Seconds

stickiness.lb_cookie.duration_seconds

  • ALB

Range(1,604800) Seconds

lambda.multi_value_headers.enabled * Works only for Lambda targets

  • ALB

  • “true”

  • “false”

deregistration_delay.connection_termination.enabled

  • NLB

  • “true”

  • “false”

preserve_client_ip.enabled

  • NLB

  • “true”

  • “false”

proxy_protocol_v2.enabled

  • NLB

  • “true”

  • “false”

Settings

NoAllocateEips

By default, when using a public NLB, ECS Compose-X will create Elastic IP (EIPs) allocations. Given this is no longer a requirement on NLBs, this boolean allows to disable this behaviour and let AWS assign IP addresses to your NLB.

RetainEips

If set to true, when provisioning the EIPs, the DeletionPolicy will be set to Retain allowing you to preserve these IP addresses should you want to re-use them later.

Examples

---
# ELBv2 creation for services


x-acm:
  public-acm-01:
    Properties:
      DomainName: test.bdd-testing.compose-x.io
      DomainValidationOptions:
        - HostedZoneId: ZABCDEFGHIS0123
          DomainName: test.bdd-testing.compose-x.io
      SubjectAlternativeNames:
        - anothertest.bdd-testing.compose-x.io
        - yet.another.test.bdd-testing.compose-x.io
      ValidationMethod: DNS

x-elbv2:
  lbA:
    Properties:
      Type: application
    MacroParameters:
      timeout_seconds: 60
      desync_mitigation_mode: defensive
      drop_invalid_header_fields: True
      http2: False
      cross_zone: True
      Ingress:
        ExtSources:
          - IPv4: "0.0.0.0/0"
            Description: ANY
          - IPv4: "1.1.1.1/32"
            Description: CLOUDFLARE
            Name: CLOUDFLARE
    Listeners:
      - Port: 80
        Protocol: HTTP
        DefaultActions:
          - Redirect: HTTP_TO_HTTPS
      - Port: 443
        Protocol: HTTP
        Certificates:
          - x-acm: public-acm-01
        Targets:
          - name: bignicefamily:app01
            access: /somewhere
      - Port: 8080
        Protocol: HTTP
        Certificates:
          - x-acm: public-acm-01
          - CertificateArn: arn:aws:acm:eu-west-1:012345678912:certificate/102402a1-d0d2-46ff-b26b-33008f072ee8
        Targets:
          - name: bignicefamily:rproxy
            access: /
          - name: youtoo:rproxy
            access: /stupid
          - name: bignicefamily:app01
            access: thereisnospoon.ews-network.net:8080/abcd/test.html

    Services:
      - name: bignicefamily:rproxy
        port: 80
        protocol: HTTP
        healthcheck: 5000:HTTP:/healthcheck:200,201
      - name: bignicefamily:app01
        port: 5000
        healthcheck: 5000:HTTP:/path/to/healthcheck:200,201
        protocol: HTTP
        TargetGroupAttributes:
          - Key: stickiness.enabled
            Value: "false"
          - Key: load_balancing.algorithm.type
            Value: least_outstanding_requests
      - name: youtoo:rproxy
        port: 80
        healthcheck: 5000:HTTP:5:2:15:3:/ping.This.Method:200,201
        protocol: HTTP
        TargetGroupAttributes:
          stickiness.enabled: "false"
          load_balancing.algorithm.type: least_outstanding_requests

  lbC:
    Properties:
      Scheme: internet-facing
      Type: network
    MacroParameters:
      cross_zone: True
    Settings: {}
    Listeners:
      - Port: 8080
        Protocol: TCP
        Targets:
          - name: app03:app03
            access: /
      - Port: 8081
        Protocol: TCP
        Certificates:
          - x-acm: public-acm-01
        Targets:
          - name: app03:app03
            access: /
    Services:
      - name: app03:app03
        port: 5000
        healthcheck: 5000:TCP:7:2:15:5
        protocol: TCP
        TargetGroupAttributes:
          deregistration_delay.timeout_seconds: "30"
          proxy_protocol_v2.enabled: "true"
          preserve_client_ip.enabled: "true"
#          - Key: deregistration_delay.timeout_seconds
#            Value: "30"
#          - Key: proxy_protocol_v2.enabled
#            Value: "true"
#          - Key: preserve_client_ip.enabled
#            Value: "true"
ELBv2 with
x-elbv2:
  authLb:
    Properties:
      Scheme: internet-facing
      Type: application
    Settings: {}
    Listeners:
      - Port: 8080
        Protocol: HTTP
        Targets:
          - name: app03:app03
            access: /
      - Port: 8081
        Protocol: HTTP
        Targets:
          - name: app03:app03
            access: /
            AuthenticateOidcConfig:
              Issuer: "{{resolve:secretsmanager:/oidc/azuread/app001:SecretString:Issuer}}"
              AuthorizationEndpoint: "{{resolve:secretsmanager:/oidc/azuread/app001:SecretString:AuthorizationEndpoint}}"
              TokenEndpoint: "{{resolve:secretsmanager:/oidc/azuread/app001:SecretString:TokenEndpoint}}"
              UserInfoEndpoint: "{{resolve:secretsmanager:/oidc/azuread/app001:SecretString:UserInfoEndpoint}}"
              ClientId: "{{resolve:secretsmanager:/oidc/azuread/app001:SecretString:ClientId}}"
              ClientSecret: "{{resolve:secretsmanager:/oidc/azuread/app001:SecretString:ClientSecret}}"
              SessionCookieName: "my-cookie"
              SessionTimeout: 3600
              Scope: "email"
              AuthenticationRequestExtraParams":
                display": "page"
                prompt": "login"
              OnUnauthenticatedRequest: "deny"
    Services:
      - name: app03:app03
        port: 5000
        healthcheck: 5000:HTTP:7:2:15:5
        protocol: HTTP

JSON Schema

Model

x-elbv2

x-elbv2.spec.json

The specifications of x-elbv2 in ComposeX

type

object

properties

  • Properties

type

object

  • Lookup

Lookup existing LoadBalancer

type

object

properties

  • loadbalancer

type

object

properties

  • Tags

Tags lookup to find the elasticloadbalancing:loadbalancer

#/definitions/LookupTags

  • Listeners

Find existing Listener. When ALB, adds new TGT and rules. Cannot be default rule. When NLB, this simply adds new Target Groups.

type

object

patternProperties

  • ^[0-9]+

type

object

properties

  • Tags

Tags to lookup elasticloadbalancing:listener

#/definitions/LookupTags

  • Targets

type

array

items

#/definitions/TargetRule

  • Certificates

#/definitions/ListenerCertificates

additionalProperties

False

  • RoleArn

RoleARN to use in AssumeRole to find the Load Balancer

type

string

  • MacroParameters

type

object

properties

  • Ingress

ingress.spec.json

additionalProperties

True

  • Listeners

type

array

items

#/definitions/Listener

  • Services

type

array

items

#/definitions/TargetDef

  • TargetGroups

Target groups, uniquely identified

type

object

patternProperties

  • ^[a-zA-Z0-9\-._]+$

Defines a target group that encompasses one or several services.

type

object

properties

  • Protocol

type

string

  • Port

type

number

maximum

65535

minimum

1

  • Services

type

array

items

type

object

properties

  • Name

Family:Container definition

type

string

  • Port

type

number

maximum

65535

minimum

1

minItems

1

  • HealthCheck

#/definitions/TargetGroupHealthCheckDef

  • TargetGroupAttributes

#/definitions/TargetGroupAttributeDef

  • Tags

oneOf

Shortcut definition of key/value tags

type

object

patternProperties

  • ^[a-zA-Z0-9._]+$

type

string

additionalProperties

False

type

array

items

Classic CFN Key/Value object for a Tag

type

object

properties

  • Key

type

string

  • Value

type

string

additionalProperties

False

additionalProperties

False

  • Settings

type

object

properties

  • Subnets

Name of the Subnets as defined in x-vpc to use

type

string

  • NoAllocateEips

Disables creating new EIPs for Network Load Balancers (NLB)

type

boolean

  • RetainEips

Retains provisioned EIPs

type

boolean

  • DnsAliases

type

array

items

#/definitions/DnsAlias

uniqueItems

True

definitions

  • LookupTags

oneOf

Tags list[Key: Value]

type

array

items

type

object

properties

  • Key

type

string

  • Value

type

string

additionalProperties

False

uniqueItems

True

Key: Value tags

type

object

patternProperties

  • ^[a-zA-Z0-9_:\-\.]+

Tag value

type

string / number

additionalProperties

False

  • DnsAlias

type

object

properties

  • Names

type

array

items

type

string

pattern

\b((?=[a-z0-9-]{1,63}\.)(xn–)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b$

format

idn-hostname

minItems

1

uniqueItems

True

  • Route53Zone

type

string

pattern

^x-route53::[\S]+$

additionalProperties

False

  • TargetDef

type

object

properties

  • name

type

string

  • protocol

#/definitions/Protocol

  • port

#/definitions/Port

  • healthcheck

#/definitions/TargetGroupHealthCheckDef

  • TargetGroupAttributes

#/definitions/TargetGroupAttributeDef

additionalProperties

False

  • TargetGroupHealthCheckDef

oneOf

type

string

Allows to define HealthCheck properties as in https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html

type

object

properties

  • HealthCheckEnabled

type

string / boolean

  • HealthCheckIntervalSeconds

type

integer

minimum

1

  • HealthCheckPath

type

string

  • HealthCheckPort

type

number

maximum

65535

minimum

1

  • HealthCheckProtocol

type

string

enum

HTTP, HTTPS, TCP, UDP, TLS, TCP_UDP

  • HealthCheckTimeoutSeconds

type

integer

minimum

1

  • HealthyThresholdCount

type

integer

minimum

1

  • UnhealthyThresholdCount

type

integer

minimum

1

  • Matcher

type

object

properties

  • GrpcCode

type

string

  • HttpCode

type

string

additionalProperties

False

additionalProperties

False

  • TargetGroupAttributeDef

oneOf

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html

type

array

items

#/definitions/TargetGroupAttribute

type

object

patternProperties

  • ^[a-zA-Z0-9._]+$

type

string

additionalProperties

False

  • TargetGroupAttribute

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-targetgroup-targetgroupattribute.html

type

object

properties

  • Key

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-targetgroup-targetgroupattribute.html

type

string

  • Value

type

string

additionalProperties

False

  • TargetRule

type

object

properties

  • name

type

string

  • access

Predefined condition on the hostname and path allowing to use human friendly syntax

type

string

  • Conditions

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listenerrule-rulecondition.html

type

array

items

type

object

  • CreateCognitoClient

Allows to create a new UserPool Client when using AuthenticateCognitoConfig and x-cognito_userpool

type

object

properties

  • UserPoolId

type

string

additionalProperties

True

  • AuthenticateCognitoConfig

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listener-authenticatecognitoconfig.html

type

object

  • AuthenticateOidcConfig

type

object

oneOf

type

object

type

object

  • Listener

type

object

properties

  • Port

#/definitions/Port

  • Protocol

#/definitions/Protocol

  • SslPolicy

type

string

  • Certificates

#/definitions/ListenerCertificates

  • DefaultActions

type

array

  • Targets

type

array

items

#/definitions/TargetRule

  • Port

type

integer

maximum

65535

minimum

1

  • Protocol

type

string

enum

HTTP, HTTPS, TCP, UDP, TCP_UDP, TLS

  • ListenerCertificates

List of pointers to an ACM Certificate.

type

array

items

The Certificate pointer. Can use (only one) either x-acm, Arn or CertificateArn

type

object

properties

  • x-acm

type

string

  • Arn

type

string

  • CertificateArn

type

string

additionalProperties

False

uniqueItems

True

Definition

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "x-elbv2.spec.json",
  "type": "object",
  "title": "x-elbv2",
  "description": "The specifications of x-elbv2 in ComposeX",
  "oneOf": [
    {
      "required": [
        "Services"
      ]
    },
    {
      "required": [
        "TargetGroups"
      ]
    }
  ],
  "properties": {
    "Properties": {
      "type": "object"
    },
    "Lookup": {
      "type": "object",
      "description": "Lookup existing LoadBalancer",
      "required": [
        "loadbalancer"
      ],
      "properties": {
        "loadbalancer": {
          "type": "object",
          "description": "",
          "properties": {
            "Tags": {
              "$ref": "#/definitions/LookupTags",
              "description": "Tags lookup to find the elasticloadbalancing:loadbalancer"
            }
          }
        },
        "Listeners": {
          "type": "object",
          "additionalProperties": false,
          "description": "Find existing Listener. When ALB, adds new TGT and rules. Cannot be default rule. When NLB, this simply adds new Target Groups.",
          "patternProperties": {
            "^[0-9]+": {
              "type": "object",
              "required": [
                "Tags",
                "Targets"
              ],
              "properties": {
                "Tags": {
                  "$ref": "#/definitions/LookupTags",
                  "description": "Tags to lookup elasticloadbalancing:listener"
                },
                "Targets": {
                  "type": "array",
                  "items": {
                    "$ref": "#/definitions/TargetRule"
                  }
                },
                "Certificates": {
                  "$ref": "#/definitions/ListenerCertificates"
                }
              }
            }
          }
        },
        "RoleArn": {
          "type": "string",
          "description": "RoleARN to use in AssumeRole to find the Load Balancer"
        }
      }
    },
    "MacroParameters": {
      "type": "object",
      "additionalProperties": true,
      "properties": {
        "Ingress": {
          "$ref": "ingress.spec.json"
        }
      }
    },
    "Listeners": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/Listener"
      }
    },
    "Services": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/TargetDef"
      }
    },
    "TargetGroups": {
      "type": "object",
      "additionalProperties": false,
      "description": "Target groups, uniquely identified",
      "patternProperties": {
        "^[a-zA-Z0-9\\-._]+$": {
          "type": "object",
          "required": [
            "Port",
            "Protocol",
            "Services",
            "HealthCheck"
          ],
          "description": "Defines a target group that encompasses one or several services.",
          "properties": {
            "Protocol": {
              "type": "string"
            },
            "Port": {
              "type": "number",
              "minimum": 1,
              "maximum": 65535
            },
            "Services": {
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "properties": {
                  "Name": {
                    "type": "string",
                    "description": "Family:Container definition"
                  },
                  "Port": {
                    "type": "number",
                    "minimum": 1,
                    "maximum": 65535
                  }
                }
              }
            },
            "HealthCheck": {
              "$ref": "#/definitions/TargetGroupHealthCheckDef"
            },
            "TargetGroupAttributes": {
              "$ref": "#/definitions/TargetGroupAttributeDef"
            },
            "Tags": {
              "oneOf": [
                {
                  "type": "object",
                  "additionalProperties": false,
                  "description": "Shortcut definition of key/value tags",
                  "patternProperties": {
                    "^[a-zA-Z0-9._]+$": {
                      "type": "string"
                    }
                  }
                },
                {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "description": "Classic CFN Key/Value object for a Tag",
                    "additionalProperties": false,
                    "properties": {
                      "Key": {
                        "type": "string"
                      },
                      "Value": {
                        "type": "string"
                      }
                    }
                  }
                }
              ]
            }
          }
        }
      }
    },
    "Settings": {
      "type": "object",
      "properties": {
        "Subnets": {
          "type": "string",
          "description": "Name of the Subnets as defined in x-vpc to use"
        },
        "NoAllocateEips": {
          "type": "boolean",
          "description": "Disables creating new EIPs for Network Load Balancers (NLB)"
        },
        "RetainEips": {
          "type": "boolean",
          "description": "Retains provisioned EIPs"
        }
      }
    },
    "DnsAliases": {
      "type": "array",
      "uniqueItems": true,
      "items": {
        "$ref": "#/definitions/DnsAlias"
      }
    }
  },
  "definitions": {
    "LookupTags": {
      "oneOf": [
        {
          "type": "array",
          "description": "Tags list[Key: Value]",
          "uniqueItems": true,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "Key": {
                "type": "string"
              },
              "Value": {
                "type": "string"
              }
            }
          }
        },
        {
          "type": "object",
          "description": "Key: Value tags",
          "additionalProperties": false,
          "patternProperties": {
            "^[a-zA-Z0-9_:\\-\\.]+": {
              "type": [
                "string",
                "number"
              ],
              "description": "Tag value"
            }
          }
        }
      ]
    },
    "DnsAlias": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "Names",
        "Route53Zone"
      ],
      "properties": {
        "Names": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "format": "idn-hostname",
            "pattern": "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b$"
          }
        },
        "Route53Zone": {
          "type": "string",
          "pattern": "^x-route53::[\\S]+$"
        }
      }
    },
    "TargetDef": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "name",
        "protocol",
        "port",
        "healthcheck"
      ],
      "properties": {
        "name": {
          "type": "string"
        },
        "protocol": {
          "$ref": "#/definitions/Protocol"
        },
        "port": {
          "$ref": "#/definitions/Port"
        },
        "healthcheck": {
          "$ref": "#/definitions/TargetGroupHealthCheckDef"
        },
        "TargetGroupAttributes": {
          "$ref": "#/definitions/TargetGroupAttributeDef"
        }
      }
    },
    "TargetGroupHealthCheckDef": {
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "object",
          "description": "Allows to define HealthCheck properties as in https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html",
          "additionalProperties": false,
          "properties": {
            "HealthCheckEnabled": {
              "type": [
                "string",
                "boolean"
              ]
            },
            "HealthCheckIntervalSeconds": {
              "type": "integer",
              "minimum": 1
            },
            "HealthCheckPath": {
              "type": "string"
            },
            "HealthCheckPort": {
              "type": "number",
              "minimum": 1,
              "maximum": 65535
            },
            "HealthCheckProtocol": {
              "type": "string",
              "enum": [
                "HTTP",
                "HTTPS",
                "TCP",
                "UDP",
                "TLS",
                "TCP_UDP"
              ]
            },
            "HealthCheckTimeoutSeconds": {
              "type": "integer",
              "minimum": 1
            },
            "HealthyThresholdCount": {
              "type": "integer",
              "minimum": 1
            },
            "UnhealthyThresholdCount": {
              "type": "integer",
              "minimum": 1
            },
            "Matcher": {
              "type": "object",
              "oneOf": [
                {
                  "required": [
                    "HttpCode"
                  ]
                },
                {
                  "required": [
                    "GrpcCode"
                  ]
                }
              ],
              "additionalProperties": false,
              "properties": {
                "GrpcCode": {
                  "type": "string"
                },
                "HttpCode": {
                  "type": "string"
                }
              }
            }
          }
        }
      ]
    },
    "TargetGroupAttributeDef": {
      "oneOf": [
        {
          "type": "array",
          "description": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-targetgroup.html",
          "items": {
            "$ref": "#/definitions/TargetGroupAttribute"
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "patternProperties": {
            "^[a-zA-Z0-9._]+$": {
              "type": "string"
            }
          }
        }
      ]
    },
    "TargetGroupAttribute": {
      "type": "object",
      "additionalProperties": false,
      "description": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-targetgroup-targetgroupattribute.html",
      "properties": {
        "Key": {
          "type": "string",
          "description": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-targetgroup-targetgroupattribute.html"
        },
        "Value": {
          "type": "string"
        }
      }
    },
    "TargetRule": {
      "type": "object",
      "required": [
        "name"
      ],
      "oneOf": [
        {
          "type": "object",
          "required": [
            "access"
          ]
        },
        {
          "type": "object",
          "required": [
            "Conditions"
          ]
        }
      ],
      "properties": {
        "name": {
          "type": "string"
        },
        "access": {
          "type": "string",
          "description": "Predefined condition on the hostname and path allowing to use human friendly syntax"
        },
        "Conditions": {
          "type": "array",
          "description": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listenerrule-rulecondition.html",
          "items": {
            "type": "object"
          }
        },
        "CreateCognitoClient": {
          "type": "object",
          "additionalProperties": true,
          "required": [
            "UserPoolId"
          ],
          "description": "Allows to create a new UserPool Client when using AuthenticateCognitoConfig and x-cognito_userpool",
          "properties": {
            "UserPoolId": {
              "type": "string"
            }
          }
        },
        "AuthenticateCognitoConfig": {
          "type": "object",
          "description": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-elasticloadbalancingv2-listener-authenticatecognitoconfig.html"
        },
        "AuthenticateOidcConfig": {
          "type": "object"
        }
      }
    },
    "Listener": {
      "type": "object",
      "oneOf": [
        {
          "required": [
            "DefaultActions"
          ]
        },
        {
          "required": [
            "Targets"
          ]
        }
      ],
      "properties": {
        "Port": {
          "$ref": "#/definitions/Port"
        },
        "Protocol": {
          "$ref": "#/definitions/Protocol"
        },
        "SslPolicy": {
          "type": "string"
        },
        "Certificates": {
          "$ref": "#/definitions/ListenerCertificates"
        },
        "DefaultActions": {
          "type": "array"
        },
        "Targets": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/TargetRule"
          }
        }
      }
    },
    "Port": {
      "type": "integer",
      "minimum": 1,
      "maximum": 65535
    },
    "Protocol": {
      "type": "string",
      "enum": [
        "HTTP",
        "HTTPS",
        "TCP",
        "UDP",
        "TCP_UDP",
        "TLS"
      ]
    },
    "ListenerCertificates": {
      "type": "array",
      "uniqueItems": true,
      "description": "List of pointers to an ACM Certificate.",
      "items": {
        "type": "object",
        "description": "The Certificate pointer. Can use (only one) either x-acm, Arn or CertificateArn",
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "x-acm"
            ]
          },
          {
            "required": [
              "Arn"
            ]
          },
          {
            "required": [
              "CertificateArn"
            ]
          }
        ],
        "properties": {
          "x-acm": {
            "type": "string"
          },
          "Arn": {
            "type": "string"
          },
          "CertificateArn": {
            "type": "string"
          }
        }
      }
    }
  }
}

Test files

You can find the test files here to use as reference for your use-case.