Skip to content

Commit da1d6f4

Browse files
authored
Domain and certs handling (#52)
* Initial commit * Removing 00_acm_create from deploy * Adding missing files * Fixing variables * Small fixes from old code * Changing lb_url for vm_url * Moved env_out file * We don't need app_port being passed * Chaging elb protocol level * Removing blank variable * Chaging cert_available lb check * Adding variables passthrough * Adding readme definitions for domains and certs * Resolving comments * Fixes
1 parent c170269 commit da1d6f4

File tree

14 files changed

+358
-229
lines changed

14 files changed

+358
-229
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ The following inputs can be used as `steps.with` keys:
7777
| `aws_create_vpc` | bool | `false` | Whether an AWS VPC should be created in the action. Otherwise, the existing default VPC will be used. |
7878
| `aws_extra_tags` | json | | A list of additional tags that will be included on created resources. Example: `{"key1": "value1", "key2": "value2"}`. |
7979
| `infrastructure_only` | bool | `false` | Set to true to provision infrastructure (with Terraform) but skip the app deployment (with ansible) |
80+
| **Domain and certificates configuration** |
81+
| `aws_domain_name` | string | | Define the root domain name for the application. e.g. bitovi.com'. If empty, ELB URL will be provided. |
82+
| `aws_sub_domain` | string | `${org}-${repo}-${branch}` | Define the sub-domain part of the URL. |
83+
| `aws_root_domain` | bool | `false` | Deploy application to root domain. Will create root and www DNS records. Domain must exist in Route53. |
84+
| `aws_cert_arn` | string | | Existing certificate ARN to be used in the ELB. Use if you manage a certificate outside of this action. See [this](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-list.html) for how to find the certificate ARN. **See note**. |
85+
| `aws_create_root_cert` | bool | `false`| Generates and manage the root certificate for the application to be used in the ELB. **See note**.|
86+
| `aws_create_sub_cert` | bool | `false` | Generates and manage the sub-domain certificate for the application to be used in the ELB. **See note**.|
87+
| `aws_no_cert` | bool | `false` | Set this to true if you want not to use a certificate in the ELB. **See note**. |
8088
| **Teraform configuration** |
8189
| `tf_state_bucket` | string | `${org}-${repo}-${branch}-tf-state` | AWS S3 bucket to use for Terraform state. By default, a new deployment will be created for each unique branch. Hardcode if you want to keep a shared resource state between the several branches. |
8290
| **StackStorm configuration** |
@@ -98,6 +106,27 @@ For some specific resources, we have a `32` characters limit. If the identifier
98106
### S3 buckets naming
99107
Bucket names can be made of up to 63 characters. If the length allows us to add `-tf-state`, we will do so. If not, a simple `-tf` will be added.
100108

109+
## Domain and Certificates - Only for AWS Managed domains with Route53
110+
111+
As a default, the application will be deployed and the ELB public URL will be displayed.
112+
113+
If `aws_domain_name` is defined, we will look up for a certificate with the name of that domain (eg. `example.com`). We expect that certificate to contain both `example.com` and `*.example.com`. Resulting URL will be `aws_sub_domain.aws_domain_name`
114+
115+
If no certificate is available for `aws_domain_name`, then set up `no_cert` to true.
116+
117+
If you want to use an already created certificate, or prefer to manage it manually, you can set up `aws_cert_arn`.
118+
Check the [AWS notes](https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-list.html) for how to find the certificate ARN in AWS.
119+
120+
Setting `aws_create_root_cert` to `true` will create this certificate with both `example.com` and `*.example.com` for you, and validate them. (DNS validation).
121+
122+
Setting `aws_create_sub_cert` to `true` will create a certificate **just for the subdomain**, and validate it.
123+
124+
> :warning: Be very careful here! **Created certificates are fully managed by Terraform**. Therefore **they will be destroyed upon stack destruction**.
125+
126+
To change a certificate (root_cert, sub_cert, ARN or pre-existing root cert), you must first set the `no_cert` flag to true, run the action, then set the `no_cert` flag to false, add the desired settings and excecute the action again. (**This will destroy the first certificate.**)
127+
128+
This is necessary due to a limitation that prevents certificates from being changed while in use by certain resources.
129+
101130
### Advanced StackStorm configuration with Ansible vars
102131
This action runs [`ansible-st2`](https://github.com/stackStorm/ansible-st2) roles under the hood. You can customize the Ansible configuration by creating a yaml file in your repo. This file will be passed to the Ansible playbook as extra vars. See the [Ansible-st2](https://github.com/stackStorm/ansible-st2#variables) documentation for a full list of available options.
103132

action.yaml

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,32 @@ inputs:
6868
description: 'Force purge and deletion of tf_state_bucket defined. Any file contained there will be destroyed. tf_stack_destroy must also be true.'
6969
default: "false"
7070

71+
# Domains
72+
aws_domain_name:
73+
description: 'Define the root domain name for the application. e.g. bitovi.com'. If empty, ELB URL will be provided.'
74+
required: false
75+
aws_sub_domain:
76+
description: 'Define the sub-domain part of the URL. Defaults to `${org}-${repo}-{branch}`'
77+
aws_root_domain:
78+
description: 'Deploy application to root domain. Will create root and www DNS records. Domain must exist in Route53.'
79+
required: false
80+
aws_cert_arn:
81+
description: 'Existing certificate ARN to be used in the ELB. Use if you manage a certificate outside of this action. See https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-list.html for how to find the certificate ARN.'
82+
required: false
83+
aws_create_root_cert:
84+
description: 'Generates and manage the root certificate for the application to be used in the ELB.'
85+
required: false
86+
aws_create_sub_cert:
87+
description: 'Generates and manage the sub-domain certificate for the application to be used in the ELB.'
88+
required: false
89+
aws_no_cert:
90+
description: 'Set this to true if you want not to use a certificate in the ELB.'
91+
required: false
92+
7193
outputs:
72-
lb_url:
94+
vm_url:
7395
description: 'The URL of the generated app'
74-
value: ${{ steps.deploy.outputs.lb_url }}
96+
value: ${{ steps.deploy.outputs.vm_url }}
7597

7698
runs:
7799
using: 'composite'
@@ -93,14 +115,21 @@ runs:
93115
TF_STATE_BUCKET: ${{ inputs.tf_state_bucket }}
94116
TF_STATE_BUCKET_DESTROY: ${{ inputs.tf_state_bucket_destroy }}
95117

96-
APP_PORT: ${{ inputs.app_port }}
97118
EC2_INSTANCE_PROFILE: ${{ inputs.aws_ec2_instance_profile }}
98119
EC2_INSTANCE_TYPE: ${{ inputs.aws_ec2_instance_type }}
99120
STACK_DESTROY: ${{ inputs.tf_stack_destroy }}
100121
AWS_RESOURCE_IDENTIFIER: ${{ inputs.aws_resource_identifier }}
101122
CREATE_VPC: ${{ inputs.aws_create_vpc }}
102123
AWS_EXTRA_TAGS: ${{ inputs.aws_extra_tags }}
103124

125+
# Domain / cert management
126+
DOMAIN_NAME: ${{ inputs.aws_domain_name }}
127+
SUB_DOMAIN: ${{ inputs.aws_sub_domain }}
128+
ROOT_DOMAIN: ${{ inputs.aws_root_domain }}
129+
CERT_ARN: ${{ inputs.aws_cert_arn }}
130+
CREATE_ROOT_CERT: ${{ inputs.aws_create_root_cert }}
131+
CREATE_SUB_CERT: ${{ inputs.aws_create_sub_cert }}
132+
NO_CERT: ${{ inputs.aws_no_cert }}
104133

105134
# Skip ansible deployment if deploying only infrastructure
106135
ANSIBLE_SKIP_DEPLOY: ${{ inputs.infrastructure_only }}
@@ -118,13 +147,13 @@ runs:
118147
$GITHUB_ACTION_PATH/operations/_scripts/deploy/export_vars.sh
119148
120149
# output results to GitHub
121-
- if: ${{ steps.deploy.outputs.lb_url != '' }}
150+
- if: ${{ steps.deploy.outputs.vm_url != '' }}
122151
name: Print result created
123152
shell: bash
124153
run: |
125154
echo "## VM Created! :rocket:" >> $GITHUB_STEP_SUMMARY
126-
echo " ${{ steps.deploy.outputs.lb_url }}" >> $GITHUB_STEP_SUMMARY
127-
- if: ${{ steps.deploy.outputs.lb_url == '' }}
155+
echo " ${{ steps.deploy.outputs.vm_url }}" >> $GITHUB_STEP_SUMMARY
156+
- if: ${{ steps.deploy.outputs.vm_url == '' }}
128157
name: Print result destroyed
129158
shell: bash
130159
run: |

operations/_scripts/deploy/deploy.sh

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ export LB_LOGS_BUCKET="$(/bin/bash $GITHUB_ACTION_PATH/operations/_scripts/gener
2525
# Generate app repo
2626
/bin/bash $GITHUB_ACTION_PATH/operations/_scripts/generate/generate_app_repo.sh
2727

28-
# Generate `00_acm_create`
29-
if [[ "$CREATE_DOMAIN" == "true" ]]; then
30-
/bin/bash $GITHUB_ACTION_PATH/operations/_scripts/generate/generate_acm_tf.sh
31-
fi
32-
3328
if [ "$STACK_DESTROY" == "true" ]; then
3429
export BITOPS_TERRAFORM_STACK_ACTION="destroy"
3530
export BITOPS_ANSIBLE_SKIP_DEPLOY="true"

operations/_scripts/generate/generate_acm_tf.sh

Lines changed: 0 additions & 60 deletions
This file was deleted.

operations/_scripts/generate/generate_tf_vars.sh

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ if [ -z "${EC2_INSTANCE_PROFILE}" ]; then
3636
fi
3737

3838
echo "
39-
app_port = \"$APP_PORT\"
40-
4139
lb_port = \"$LB_PORT\"
4240
43-
lb_healthcheck = \"$LB_HEALTHCHECK\"
44-
4541
# the name of the operations repo environment directory
4642
ops_repo_environment = \"deployment\"
4743
@@ -75,6 +71,13 @@ aws_resource_identifier_supershort = \"${GITHUB_IDENTIFIER_SS}\"
7571
sub_domain_name = \"${SUB_DOMAIN}\"
7672
domain_name = \"${DOMAIN_NAME}\"
7773
74+
# Cert stuff
75+
root_domain = \"${ROOT_DOMAIN}\"
76+
cert_arn = \"${CERT_ARN}\"
77+
create_root_cert = \"${CREATE_ROOT_CERT}\"
78+
create_sub_cert = \"${CREATE_SUB_CERT}\"
79+
no_cert = \"${NO_CERT}\"
80+
7881
# VPC
7982
create_vpc = \"${CREATE_VPC}\"
8083

operations/deployment/terraform/main.tf

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,22 @@ module "Stackstorm-Single-VM" {
1616
lb_access_bucket_name=var.lb_access_bucket_name
1717
aws_resource_identifier=var.aws_resource_identifier
1818
aws_resource_identifier_supershort=var.aws_resource_identifier_supershort
19-
sub_domain_name=var.sub_domain_name
20-
domain_name=var.domain_name
2119
create_vpc=var.create_vpc
2220
#create_domain=var.create_domain
2321
availability_zones=local.availability_zones
24-
route53_zone_id=var.route53_zone_id
22+
#route53_zone_id=var.route53_zone_id
23+
sub_domain_name=var.sub_domain_name
24+
domain_name=var.domain_name
25+
root_domain=var.root_domain
26+
cert_arn=var.cert_arn
27+
create_root_cert=var.create_root_cert
28+
create_sub_cert=var.create_sub_cert
29+
no_cert=var.no_cert
2530
}
2631

2732
locals {
2833
availability_zones = "${formatlist("${var.region}%s", var.availability_zones)}"
29-
url = "${module.Stackstorm-Single-VM.loadbalancer_protocol}${module.Stackstorm-Single-VM.loadbalancer_public_dns}"
34+
#url = "${module.Stackstorm-Single-VM.loadbalancer_protocol}${module.Stackstorm-Single-VM.loadbalancer_public_dns}"
3035
}
3136

3237
output "availability_zone" {
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Lookup for main domain.
2+
3+
data "aws_acm_certificate" "issued" {
4+
count = var.no_cert == "true" ? 0 : (var.create_root_cert != "true" ? (var.create_sub_cert != "true" ? (local.fqdn_provided ? 1 : 0) : 0) : 0)
5+
domain = var.domain_name
6+
}
7+
8+
# This block will create and validate the root domain and www cert
9+
resource "aws_acm_certificate" "root_domain" {
10+
count = var.create_root_cert == "true" ? (var.domain_name != "" ? 1 : 0) : 0
11+
domain_name = var.domain_name
12+
subject_alternative_names = ["*.${var.domain_name}", "${var.domain_name}"]
13+
validation_method = "DNS"
14+
}
15+
16+
resource "aws_route53_record" "root_domain" {
17+
count = var.create_root_cert == "true" ? (var.domain_name != "" ? 1 : 0) : 0
18+
allow_overwrite = true
19+
name = tolist(aws_acm_certificate.root_domain[0].domain_validation_options)[0].resource_record_name
20+
records = [tolist(aws_acm_certificate.root_domain[0].domain_validation_options)[0].resource_record_value]
21+
type = tolist(aws_acm_certificate.root_domain[0].domain_validation_options)[0].resource_record_type
22+
zone_id = data.aws_route53_zone.selected[0].zone_id
23+
ttl = 60
24+
}
25+
26+
resource "aws_acm_certificate_validation" "root_domain" {
27+
count = var.create_root_cert == "true" ? (var.domain_name != "" ? 1 : 0) : 0
28+
certificate_arn = aws_acm_certificate.root_domain[0].arn
29+
validation_record_fqdns = [for record in aws_route53_record.root_domain : record.fqdn]
30+
}
31+
32+
33+
# This block will create and validate the sub domain cert ONLY
34+
resource "aws_acm_certificate" "sub_domain" {
35+
count = var.create_sub_cert == "true" ? (var.domain_name != "" ? (var.sub_domain_name != "" ? 1 : 0) : 0) : 0
36+
domain_name = "${var.sub_domain_name}.${var.domain_name}"
37+
validation_method = "DNS"
38+
}
39+
40+
resource "aws_route53_record" "sub_domain" {
41+
count = var.create_sub_cert == "true" ? (var.domain_name != "" ? (var.sub_domain_name != "" ? 1 : 0) : 0) : 0
42+
allow_overwrite = true
43+
name = tolist(aws_acm_certificate.sub_domain[0].domain_validation_options)[0].resource_record_name
44+
records = [tolist(aws_acm_certificate.sub_domain[0].domain_validation_options)[0].resource_record_value]
45+
type = tolist(aws_acm_certificate.sub_domain[0].domain_validation_options)[0].resource_record_type
46+
zone_id = data.aws_route53_zone.selected[0].zone_id
47+
ttl = 60
48+
}
49+
50+
resource "aws_acm_certificate_validation" "sub_domain" {
51+
count = var.create_sub_cert == "true" ? (var.domain_name != "" ? 1 : 0) : 0
52+
certificate_arn = aws_acm_certificate.sub_domain[0].arn
53+
validation_record_fqdns = [for record in aws_route53_record.sub_domain : record.fqdn]
54+
}
55+
56+
locals {
57+
selected_arn = (
58+
var.no_cert == "true" ? "" :
59+
(var.cert_arn != "" ? var.cert_arn :
60+
(var.create_root_cert != "true" ?
61+
(var.create_sub_cert != "true" ?
62+
(local.fqdn_provided ? data.aws_acm_certificate.issued[0].arn : "")
63+
: aws_acm_certificate.sub_domain[0].arn
64+
) : aws_acm_certificate.root_domain[0].arn
65+
)
66+
)
67+
)
68+
cert_available = (
69+
var.no_cert == "true" ? false :
70+
(var.cert_arn != "" ? true :
71+
(var.create_root_cert != "true" ?
72+
(var.create_sub_cert != "true" ?
73+
(local.fqdn_provided ? true : false)
74+
: true
75+
) : true
76+
)
77+
)
78+
)
79+
}
80+
81+
output "selected_arn" {
82+
value = local.selected_arn
83+
}

operations/deployment/terraform/modules/01_acm.tf.skip

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)