Using AWS Certificate Manager (ACM Certificate) with Elastic Beanstalk - amazon-web-services

When you have a certificate for your domain issued through AWS Certificate Manager, how do you apply that certificate to an Elastic Beanstalk application.
Yes, the Elastic Beanstalk application is load balanced and does have an ELB associated with it.
I know I can apply it directly to the ELB my self. But I want to apply it through Elastic Beanstalk so the env configuration is saved onto the Cloud Formation template.

I found out, you cannot do it through the elastic beanstalk console (at least not yet). However you can still set it via the eb cli, or aws cli.
Using EB CLI
Basically what we are trying to do is to update the aws:elb:listener setting, you can see the possible settings in the general options docs.
Using the EB CLI is pretty simple. Assuming we already setup the awsebcli tool for our project we can use the eb config command.
It will open up your default terminal editor and allow you to change settings which are written as a YAML file. When you make a change and save it, the eb config cmd will automatically update the settings for your Elastic Beanstalk environment.
You will need to add the following settings to your config file:
aws:elb:listener:443:
InstancePort: '80'
InstanceProtocol: HTTP
ListenerEnabled: 'true'
ListenerProtocol: HTTPS
PolicyNames: null
SSLCertificateId: CERTIFICATE_ARN_HERE
Change the value for CERTIFICATE_ARN_HERE to your AMC Certificates ARN. You can find it in the AWS Certificate Manager console:
IMPORTANT: Your aws:elb:listener:443 setting MUST be placed above the aws:elb:listener:80 setting. Otherwise the environment configuration update will error out.
Using AWS CLI
The same can be accomplished using the general aws cli tools via the update-environment command.
aws elasticbeanstalk update-environment \
--environment-name APPLICATION_ENV --option-settings \
Namespace=aws:elb:listener:443,OptionName=InstancePort,Value=80 \
Namespace=aws:elb:listener:443,OptionName=InstanceProtocol,Value=HTTP \
Namespace=aws:elb:listener:443,OptionName=ListenerProtocol,Value=HTTPS \
Namespace=aws:elb:listener:443,OptionName=SSLCertificateId,Value=CERTIFICATE_ARN_HERE
NOTE: When you update it via either of the methods above, the Elastic Beanstalk console will not show HTTPS as enabled. But the load balancer will, and it will also apply to the Cloudformation template as well get saved into the EB's configuration.

I find the simplest way is change the EB Load Balancer via the user console. Click change and select the new ACM certificate.
When you view the EB configuration, it will not appear, but it will be set

You can do this purely with CloudFormation; however, as seems to be quite common with Elastic Beanstalk the configuration options are much harder to find in the docs than they are for the individual components that comprise Elastic Beanstalk. The info is here:
http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-elbloadbalancer
But basically what you need to do is add the creation of the cert to your template and then reference it in OptionSettings in AWS::ElasticBeanstalk::ConfigurationTemplate:
"Certificate" : {
"Type": "AWS::CertificateManager::Certificate",
"Properties": {
"DomainName": "example.com",
}
},
// ...
"ElasticbeanstalkTemplate": {
"Type": "AWS::ElasticBeanstalk::ConfigurationTemplate",
"Properties": {
"SolutionStackName": "MyEBStack",
"ApplicationName": "MyAppName",
"Description": "",
"OptionSettings": [{
"Namespace": "aws:elb:listener:443",
"OptionName": "InstancePort",
"Value": "80"
}, {
"Namespace": "aws:elb:listener:443",
"OptionName": "InstanceProtocol",
"Value": "HTTP"
}, {
"Namespace": "aws:elb:listener:443",
"OptionName": "ListenerProtocol",
"Value": "HTTPS"
}, {
"Namespace": "aws:elb:listener:443",
"OptionName": "SSLCertificateId",
"Value": {
"Ref": "Certificate"
}
}, /*More settings*/]

Check in which zone you created the certificate and if it matches the Elastic Beanstalk zone. I had them in different zones so it didn't work.

Related

Selecting an RDS DB for newly created secrets in AWS CLI

While I try to create a new secrets for RDS using AWS CLI, I couldn't find the way where I could associate my secrets to RDS DB on creation itself.I have gone through the AWS CLI(https://docs.aws.amazon.com/cli/latest/reference/secretsmanager/create-secret.html) and wasn't able to find a way for its association.
Do I need to do this step manually by logging into the console or could this be automated in some way?
Could anyone please help.
Thanks.
The association is only based on the form of the secret-string. For the RDS the forms are listed here.
For instance, for mysql the form of the secret-string is as follows:
{
"engine": "mysql",
"host": "<required: instance host name/resolvable DNS name>",
"username": "<required: username>",
"password": "<required: password>",
"dbname": "<optional: database name. If not specified, defaults to None>",
"port": "<optional: TCP port number. If not specified, defaults to 3306>"
}
Thus, to create the secret for mysql using CLI:
Create file called mydb.json (example):
{
"username": "admin",
"password": "asdf435325gfdg",
"engine": "mysql",
"host": "database-2.cba4sasaubqv.us-east-1.rds.amazonaws.com",
"port": 3306,
"dbInstanceIdentifier": "database-2"
}
Execute:
aws secretsmanager create-secret --name mysql-info --secret-string file://mydb.json
The more confusing CLI part begins when you want to enable an automatic secret rotations. I will just leave a link for that (it also has CLI info) if you are interested in this as well:
Enabling Rotation for an Amazon RDS Database Secret

How to enable AWS Elastic Beanstalk health rule 'Ignore load balancer 4xx' through code?

The latest AWS Elastic Beanstalk (EB) console has, under each environment health configuration, a new option to ignore load balancer 4xx errors:
This same option doesn't appear on the previous AWS console version, only on the latest.
I'm trying to enable this option through code, but I can't find any docs for it. I'm already enabling the "Ignore application 4xx" option through .ebextensions.
I already did this:
Went through the EB release notes to see if I missed the announcement. No luck.
Looked to the docs for the application 4xx feature, and it doesn't mention anything about a load balancer 4xx option.
Went to the EB public roadmap and found nothing there either.
Any idea on how to configure it by code? Maybe AWS forgot to hide that option on the latest console?
I found the name of the configuration by:
Updating the configuration once from the AWS console for any environment.
Saving that configuration as an Elastic Beanstalk Saved Configuration.
Retrieving the just saved configuration with the EB CLI.
The configuration document I got back looks like this:
{
"Rules": {
"Environment": {
"ELB": {
"ELBRequests4xx": {
"Enabled": false
}
},
"Application": {
"ApplicationRequests4xx": {
"Enabled": false
}
}
}
}
}
I can now use this JSON as a ConfigDocument on my .ebextension .config file and it works!
I also documented the whole process here.

How to include sticky session in AWS Elastic Beanstalk using Cloud Formation template

As I searched for the stickiness in Elastic Beanstalk I didn't find the way how to include it using AWS Cloud Formation. Can anyone help me to do that thing.
Thanks in advance.
If we see the definition of sticky sessions, it says "Sticky sessions are a mechanism to route requests to the same target in a target group".
In Elastic Beanstalk, a target group is represented by a process. So we need to set up stickiness at process level using option settings
You can take 2 approaches here : ( below is for "default" process, if you have configured additional processes then modify accordingly but implementation remains same )
option setting namespace : aws:elasticbeanstalk:environment:process:default
Valid options to set : StickinessEnabled, StickinessLBCookieDuration
Specify option settings in your CloudFormation template under the AWS::ElasticBeanstalk::Environment Type, like described.
sample :
"Environment": {
"Properties": {
"ApplicationName": {
"Ref": "Application"
},
"Description": "AWS Elastic Beanstalk Environment running Python Sample Application",
"SolutionStackName": {
"Ref": "SolutionStackName"
},
"VersionLabel": "Initial Version",
"OptionSettings": [
{
"Namespace": "aws:elasticbeanstalk:environment:process:default",
"OptionName": "StickinessEnabled",
"Value":"true"
},
{
"Namespace": "aws:elasticbeanstalk:environment:process:default",
"OptionName": "StickinessLBCookieDuration",
"Value":"43200"
}
]
},
"Type": "AWS::ElasticBeanstalk::Environment"
}
Configure this at the source bundle level, i.e, create a .config file ( say albstickiness.config ) and place it in .ebextensions folder. In the .config file set stickiness for the ALB process.
sample can be found here under the sub heading ".ebextensions/alb-default-process.config"
you can try the below
LBCookieStickinessPolicy:
- PolicyName: myLBPolicy
CookieExpirationPeriod: '180'
you can read more about the sticky session here and here

Register AWS ECS task in service discovery namespace (private hosted zone)

I'm quite bad at using AWS but I'm trying to automate the set up of an ECS cluster with private DNS names in route53, using the new service discovery mechanism. I am able to click my way through the AWS UI to accomplish a DNS entry showing up in a private hosted zone but I cannot figure out the JSON parameters to add to the json for the command below to accomplish the same thing.
aws ecs create-service --cli-input-json file://aws/createService.json
and below is the approximate contents of the createService.json
referenced above
"cluster": "clustername",
"serviceName": "servicename",
"taskDefinition": "taskname",
"desiredCount": 1,
// here is where I'm guessing there should be some DNS config referencing some
// namespace or similar that I cannot figure out...
"networkConfiguration": {
"awsvpcConfiguration": {
"subnets": [
"subnet-11111111"
],
"securityGroups": [
"sg-111111111"
],
"assignPublicIp": "DISABLED"
}
}
I'd be grateful for any ideas since my googling skills apparently aren't good enough for this problem as it seems. Many thanks!
To automatically have an ECS service register instances into a servicediscovery service you can use the serviceRegistries attribute. Add the following to the ECS service definition json:
{
...
"serviceRegistries": [
{
"registryArn": "arn:aws:servicediscovery:region:aws_account_id:service/srv-utcrh6wavdkggqtk"
}
]
}
The attribute contains a list of autodiscovery services that should be updated by ECS when it creates or destroys a task as part of the service. Each registry is referenced using the ARN of the autodiscovery service.
To get the Arn use the AWS cli command aws servicediscovery list-services
Strangely the documentation of the ECS service definition does not contain information about this attribute. However this tutorial about service discovery does.
As it turns out there is no support in ecs create service for adding it to the service registry, i.e. the route53 private hosted zone. Instead I had to use aws servicediscovery create-service and then servicediscovery register-instance to finally get an entry in my private hosted zone.
This became a quite complicated solution so I'll instead give Terraform a shot at it since I found they recently added support for ECS service discovery and see where that takes me...

AWS Elastic Beanstalk - how to get URL though CLI

I am fairly new to AWS, I wrote a script to create a ElasticBeanstalk server and deploy code to it which works fine
I am able to get the IP Address and Instance ID using
aws ec2 describe-instances
I know a typical HTTP URL looks like this
http://(cname-prefix).(region).elasticbeanstalk.com
and I used it to "generate" the URL in the script
But I want to check if we can get the URL using CLI
The AWS CLI has a command for this, it describes the elastic beanstalk environment and one of the resulting values is the Endpoint URL
For load-balanced, autoscaling environments, it returns the URL to the LoadBalancer. For single-instance environments, the IP address of the instance is returned.
See docs
aws elasticbeanstalk describe-environments --environment-names my-env
The output looks like this:
{
"Environments": [
{
"ApplicationName": "my-app",
"EnvironmentName": "my-env",
"VersionLabel": "7f58-stage-150812_025409",
"Status": "Ready",
"EnvironmentId": "e-rpqsewtp2j",
"EndpointURL": "awseb-e-w-AWSEBLoa-1483140XB0Q4L-109QXY8121.us-west-2.elb.amazonaws.com",
"SolutionStackName": "64bit Amazon Linux 2015.03 v2.0.0 running Tomcat 8 Java 8",
"CNAME": "my-env.elasticbeanstalk.com",
"Health": "Green",
"AbortableOperationInProgress": false,
"Tier": {
"Version": " ",
"Type": "Standard",
"Name": "WebServer"
},
"DateUpdated": "2015-08-12T18:16:55.019Z",
"DateCreated": "2015-08-07T20:48:49.599Z"
}
]
}