Arjan
Arjan

Reputation: 1113

AWS CDK: how to target an Elastic Beanstalk Environment with a Route53 Alias Record

To create an Elastic Beanstalk Application and Environment I have the following code:

// this: the class instance extending Construct

const application = new CfnApplication(this, 'Application', {
  applicationName: 'some-name'
});
const environment = new CfnEnvironment(this, 'Environment', {
  environmentName: 'production',
  applicationName: application.applicationName,
  platformArn: 'arn::of::plaform',
  solutionStackName: 'a-valid-stack-name'
});

Creating an alias record in Route53 requires a target implementing IAliasRecordTarget

const record = new AliasRecord(this, 'ARecord', {
 recordName: 'a-record',
 target: ?
 zone: zone
});

How can I use the environment as target? Looking for classes implementing IAliasRecordTarget in the aws-cdk repo does not yield many candidates beside cloudfront distribution and base load balancer

Upvotes: 5

Views: 2552

Answers (4)

Arjan
Arjan

Reputation: 1113

In addition to the solution and comment posted by @jogold, using the HostedZoneProvider, to retreive your own hosted zone and using the zone id of the Elastic Beanstalk Hosted zone as target

const zone = new HostedZoneProvider(this, {
            domainName: props.domainName
}).findAndImport(this, 'a-hosted-zone');

const ebsRegionHostedZoneId = 'Z117KPS5GTRQ2G' // us-east-1

const record = new AliasRecord(this, 'ARecord', {
  recordName: 'a-record',
  target: {
    asAliasRecordTarget: (): AliasRecordTargetProps => ({
      dnsName: environment.environmentEndpointUrl,
      // the id of the hosted zone in your region
      hostedZoneId: ebsRegionHostedZoneId
    })
  },
  // your hosted zone
  zone: zone
});

Upvotes: 1

GuyT
GuyT

Reputation: 4416

For those who are looking for a solution in case of a single instance environment:

  1. Set the cnamePrefix in your EBS Environment to a value you like (eg. 'my-app'). This results in a url you can use later as part of the dnsName to create an A-record;
  2. Create an AliasRecordTarget:
const record: IAliasRecordTarget = {
                bind: (): AliasRecordTargetConfig => ({
                  dnsName: `${cnamePrefix}.${this.region}.elasticbeanstalk.com`,
                  hostedZoneId: 'Z2NYPWQ7DFZAZH' // Lookup ID or create a mapper: https://www.rubydoc.info/gems/roadworker/Aws/Route53 
                })
              };
  1. Create the A-record:
// Route53 alias record for the EBS app
new ARecord(this, 'ebs-alias-record', {
              recordName: `my-app.mydomain.com.`,
              target: RecordTarget.fromAlias(record),
              zone: hostedZone
            })

** Edit **

To get the value of the hostedZone variable you can lookup your zone by using:

HostedZone.fromLookup(this, 'zone-lookup', {domainName: 'my-app.mydomain.com'});

Upvotes: 4

Ryan
Ryan

Reputation: 1544

Here's a workaround that allows you to forward requests to the EBS environment URL (not the load balancer).

import { ARecord, RecordTarget, HostedZone, AliasRecordTargetConfig } from '@aws-cdk/aws-route53';

// Environment URL for my EBS app.
const EBS_ENV_URL = 'mysampleenvironment.eba-8mmp67ym.us-east-1.elasticbeanstalk.com';

// Id of the hosted zone in the region your EBS environment is located.
const EBS_ENV_HOSTED_ZONE_ID = 'Z117KPS5GTRQ2G';

const aliasRecord = new ARecord(stack, 'AliasRecord', {
  recordName: DOMAIN,
  target: RecordTarget.fromAlias({
    bind: (): AliasRecordTargetConfig => ({
      dnsName: EBS_ENV_URL,
      hostedZoneId: EBS_ENV_HOSTED_ZONE_ID 
    })
  }),
  zone: HostedZone.fromLookup(stack, 'WebsiteHostedZone', {
    domainName: DOMAIN
  })
});

This workaround is basically implementing a custom IAliasRecordTarget.

  1. Hardcode the EBS app’s environment URL into the dnsName prop.
  2. Visit https://docs.aws.amazon.com/general/latest/gr/elasticbeanstalk.html and find the hosted zone id that matches the region of the EBS app’s environment. This value will need to be hardcoded in the hostedZoneId prop.

Upvotes: 2

jogold
jogold

Reputation: 7407

The target prop expects an object with a bind() function returning dnsName, evaluateTargetHealth and hostedZoneId (see AWS::Route53::RecordSet AliasTarget and the implementation of AliasRecord).

You can do the following:

const record = new AliasRecord(this, 'ARecord', {
  recordName: 'a-record',
  target: {
    bind: (): AliasRecordTargetProps => ({
      dnsName: environment.attrEndpointUrl,
      hostedZoneId: 'Z14LCN19Q5QHIC' // for us-east-2
    })
  },
  zone: zone
});

See AWS Elastic Beanstalk endpoints and quotas for a list of hosted zone IDs if using another region or Elastic Load Balancing endpoints and quotas when the environment is load-balanced.

UPDATE 2018-05-28: asAliasRecordTarget is now bind in aws-cdk version 0.32.0

Upvotes: 2

Related Questions