#Application Load Balancer

Application Load Balancers can be used to re-route requests when certain traffic patterns are met. While traffic can be routed to services such as EC2 it can also be routed to Lambda functions which can in turn be used process incoming requests.

The Serverless Framework makes it possible to setup the connection between Application Load Balancers and Lambda functions with the help of the alb event.

#Event definition

functions:
  albEventConsumer:
    handler: handler.hello
    events:
      - alb:
          listenerArn: arn:aws:elasticloadbalancing:us-east-1:12345:listener/app/my-load-balancer/50dc6c495c0c9188/
          priority: 1
          conditions:
            path: /hello

#Using different conditions

functions:
  albEventConsumer:
    handler: handler.hello
    events:
      - alb:
          listenerArn: arn:aws:elasticloadbalancing:us-east-1:12345:listener/app/my-load-balancer/50dc6c495c0c9188/
          priority: 1
          conditions:
            host: example.com
            path: /hello
            method:
              - POST
              - PATCH
            host:
              - example.com
              - example2.com
            header:
              name: foo
              values:
                - bar
            query:
              bar: true
            ip:
              - fe80:0000:0000:0000:0204:61ff:fe9d:f156/6
              - 192.168.0.1/0

#Add cognito/custom idp provider authentication

With AWS you can configure an Application Load Balancer to securely authenticate users as they access your applications. To securely authenticate using Cognito and/or a identity provider (IdP) that is OpenID Connect (OIDC) compliant, follow below steps.

#1. Declare authorizer objects either of type "cognito" and/or "oidc" on provider.alb.authorizers

provider:
  alb:
    authorizers:
      myFirstAuth:
        type: 'cognito'
        userPoolArn: 'arn:aws:cognito-idp:us-east-1:123412341234:userpool/us-east-1_123412341', # required
        userPoolClientId: '1h57kf5cpq17m0eml12EXAMPLE', # required
        userPoolDomain: 'your-test-domain' # required
        allowUnauthenticated: true # If set to true this allows the request to be forwarded to the target when user is not authenticated. Omit this parameter to make a HTTP 401 Unauthorized error be returned instead
        requestExtraParams: # optional. The query parameters (up to 10) to include in the redirect request to the authorization endpoint
          prompt: 'login'
          redirect: false
        scope: 'first_name age' # Can be a combination of any system-reserved scopes or custom scopes associated with the client. The default is openid
        sessionCookieName: '🍪' # The name of the cookie used to maintain session information. The default is AWSELBAuthSessionCookie
        sessionTimeout: 7000 # The maximum duration of the authentication session, in seconds. The default is 604800 seconds (7 days).
      mySecondAuth:
        type: 'oidc'
        authorizationEndpoint: 'https://example.com', # required. The authorization endpoint of the IdP. Must be a full URL, including the HTTPS protocol, the domain, and the path
        clientId: 'i-am-client', # required
        clientSecret: 'i-am-secret', # if creating a rule this is required. If modifying a rule, this can be omitted if you set useExistingClientSecret to true (as below)
        useExistingClientSecret: true # only required if clientSecret is omitted
        issuer: 'https://www.iamscam.com', # required. The OIDC issuer identifier of the IdP. This must be a full URL, including the HTTPS protocol, the domain, and the path
        tokenEndpoint: 'http://somewhere.org', # required
        userInfoEndpoint: 'https://another-example.com' # required
        allowUnauthenticated: true # If set to true this allows the request to be forwarded to the target when user is not authenticated. Omit this parameter to make a HTTP 401 Unauthorized error be returned instead
        requestExtraParams:
          prompt: 'login'
          redirect: false
        scope: 'first_name age'
        sessionCookieName: '🍪'
        sessionTimeout: 7000

#2. Configure endpoints which are expected to have restricted access with "authorizer" parameter:

functions:
  albEventConsumer:
    handler: handler.auth
    events:
      - alb:
          listenerArn: arn:aws:elasticloadbalancing:us-east-1:12345:listener/app/my-load-balancer/50dc6c495c0c9188/
          priority: 1
          conditions:
            path: /auth/cognito
          authorizer: myFirstAuth
functions:
  albEventConsumer:
    handler: handler.auth
    events:
      - alb:
          listenerArn: arn:aws:elasticloadbalancing:us-east-1:12345:listener/app/my-load-balancer/50dc6c495c0c9188/
          priority: 1
          conditions:
            path: /auth/idp
          authorizer:
            - myFirstAuth
            - mySecondAuth

#Enabling multi-value headers

By default when the request contains a duplicate header field name or query parameter key, the load balancer uses the last value sent by the client.

Set the multiValueHeaders attribute to true if you want to receive headers and query parameters as an array of values.

functions:
  albEventConsumer:
    handler: handler.hello
    events:
      - alb:
          listenerArn: arn:aws:elasticloadbalancing:us-east-1:12345:listener/app/my-load-balancer/50dc6c495c0c9188/
          priority: 1
          multiValueHeaders: true
          conditions:
            path: /hello

When this option is enabled, the event structure is changed:

module.exports.hello = async (event, context, callback) => {
  const headers = event.multiValueHeaders;
  const queryString = event.multiValueQueryStringParameters;

  ...

  return {
    statusCode: 200,
    statusDescription: '200 OK',
    isBase64Encoded: false,
    multiValueHeaders: {
      'Content-Type': ['application/json'],
      'Set-Cookie': ['language=en-us', 'theme=rust']
    }
  };
};

The handler response object must use multiValueHeaders to set HTTP response headers, headers would be ignored.

#Prepending a prefix to generated target group names

By default, target group names are strings generated by hashing a combined string of the function name, alb's id and whether multi-value headers are enabled. This produces a fixed length, unique id for target groups.

If you need target group names to have a common predictable prefix, you may preset the prefix with the provider.alb.targetGroupPrefix setting. Note maximum length of this prefix is 16 chars.

provider:
  alb:
    targetGroupPrefix: my-prefix

functions:
  albEventConsumer:
    handler: handler.hello
    events:
      - alb:
          listenerArn: arn:aws:elasticloadbalancing:us-east-1:12345:listener/app/my-load-balancer/50dc6c495c0c9188/
          priority: 1
          conditions:
            path: /hello

Have questions?

Head over to the forums to search for your questions and issues or post a new one.