Skip to content
This repository was archived by the owner on Aug 7, 2020. It is now read-only.

Commit 9423b4d

Browse files
authored
Terraform support (#32)
Initial terraform code.
1 parent 2bb81c2 commit 9423b4d

File tree

3 files changed

+272
-0
lines changed

3 files changed

+272
-0
lines changed

terraform/.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Created by https://www.gitignore.io/api/terraform
2+
# Edit at https://www.gitignore.io/?templates=terraform
3+
4+
### Terraform ###
5+
# Local .terraform directories
6+
**/.terraform/*
7+
8+
# .tfstate files
9+
*.tfstate
10+
*.tfstate.*
11+
12+
# Crash log files
13+
crash.log
14+
15+
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
16+
# .tfvars files are managed as part of configuration and so should be included in
17+
# version control.
18+
#
19+
# example.tfvars
20+
21+
# Ignore override files as they are usually used to override resources locally and so
22+
# are not checked in
23+
override.tf
24+
override.tf.json
25+
*_override.tf
26+
*_override.tf.json
27+
28+
# Include override files you do wish to add to version control using negated pattern
29+
# !example_override.tf
30+
31+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
32+
# example: *tfplan*
33+
34+
# End of https://www.gitignore.io/api/terraform

terraform/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Terraform support (experimental)
2+
3+
## Overview
4+
5+
This folder contains a terraform file to create an Azure Resource Group with all the necessary infrastructure to deploy the AlwaysEncryptedSample app to (in theory).
6+
7+
All thise commands assume you are in the `/terraform/` folder in the git repo. The best way to ensure you are there (assuming your terminals working directory is anywhere in the git repo) is `Join-Path -Path "$(git rev-parse --show-toplevel)" -childpath 'terraform' | Set-Location`
8+
9+
## Howto
10+
11+
### Creating the resource group
12+
13+
```powershell
14+
az login
15+
az account set --subscription='SUBSCRIPTION_ID_I_WANT_TO_USE'
16+
$env:TF_VAR_certificate_creator = $(az ad signed-in-user show --query objectId --otsv)
17+
terraform init
18+
terraform plan
19+
terraform apply
20+
```
21+
22+
### Cleaning up
23+
24+
If you don't want to rack of charges then the command is `az group delete --name AlwaysEncryptedSample`. You are also going to want to delete your terraform state (i.e. the `terraform.tfstate` file, hereafter referred to as tfstate) after deleting the reource grouns as your next `terraform apply` will fail otherwise. The tfstate associates the terraform objects in your `.tf` files with the guid identifiers of the azure resources. I haven't looked to hard into the details, but the script as is can't create everything from scratch if there is an existing tfstate. Therefore you probably want to do the following:
25+
26+
```powershell
27+
az group delete --name AlwaysEncryptedSample
28+
Remove-Item -Path .\terraform.tfstate
29+
Remove-Item -Path .\terraform.tfstate.backup
30+
```
31+
32+
## Further directions
33+
34+
* I'd like t0 store the state in Azure cloud storage and just be smarter about things.

terraform/main.tf

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
data "azurerm_client_config" "current" {
2+
3+
}
4+
5+
output "tenant_id" {
6+
value = "${data.azurerm_client_config.current.tenant_id}"
7+
}
8+
9+
variable "resource_location" {
10+
type = "string"
11+
default = "East US"
12+
}
13+
14+
variable "certificate_creator" {
15+
type = "string"
16+
default = ""
17+
}
18+
19+
variable "resource_names" {
20+
type = "map"
21+
default = {
22+
"ApplicationInsights" = "AlwaysEncryptedSample"
23+
"AppServicePlan" = "always-encrypted-sample-appserviceplan"
24+
"ResourceGroup" = "AlwaysEncryptedSample"
25+
"SqlServer" = "alwaysencryptedsample"
26+
"SqlDatabase" = "AlwaysEncryptedSample"
27+
"AppService" = "AlwaysEncryptedSampleWeb3"
28+
"KeyVault" = "AlwaysEncryptedSampleKeyVault"
29+
"ColumnCertificate" = "ColumnCertificate"
30+
}
31+
32+
}
33+
variable "certificate_cn" {
34+
type = "string"
35+
default = "CN=Always Encrypted Sample Cert"
36+
}
37+
38+
variable "sql_settings" {
39+
type = "map"
40+
default = {
41+
"admin_login" = "essay"
42+
"admin_password" = "lbDG62XZy6i3pL8aC%Lw%uY7RYLN8o3aG2XhaH8dM2wbu0NPCMo0R"
43+
}
44+
}
45+
46+
resource "azurerm_resource_group" "always_encrypted_sample" {
47+
name = "${var.resource_names["ResourceGroup"]}"
48+
location = "${var.resource_location}"
49+
}
50+
51+
resource "azurerm_app_service_plan" "always_encrypted_sample" {
52+
name = "${var.resource_names["AppServicePlan"]}"
53+
location = "${azurerm_resource_group.always_encrypted_sample.location}"
54+
resource_group_name = "${azurerm_resource_group.always_encrypted_sample.name}"
55+
kind = "app"
56+
sku {
57+
tier = "Free"
58+
size = "F1"
59+
}
60+
}
61+
62+
resource "azurerm_application_insights" "app_insights" {
63+
name = "${var.resource_names["ApplicationInsights"]}"
64+
resource_group_name = "${azurerm_resource_group.always_encrypted_sample.name}"
65+
location = "${azurerm_resource_group.always_encrypted_sample.location}"
66+
application_type = "Web"
67+
}
68+
69+
output "instrumentation_key" {
70+
value = "${azurerm_application_insights.app_insights.instrumentation_key}"
71+
}
72+
73+
74+
resource "azurerm_sql_server" "sql_server" {
75+
name = "${var.resource_names["SqlServer"]}"
76+
resource_group_name = "${azurerm_resource_group.always_encrypted_sample.name}"
77+
location = "${azurerm_resource_group.always_encrypted_sample.location}"
78+
version = "12.0"
79+
administrator_login = "${var.sql_settings["admin_login"]}"
80+
administrator_login_password = "${var.sql_settings["admin_password"]}"
81+
lifecycle {
82+
ignore_changes = ["administrator_login_password"]
83+
}
84+
}
85+
86+
resource "azurerm_sql_database" "sql_database" {
87+
name = "${var.resource_names["SqlDatabase"]}"
88+
resource_group_name = "${azurerm_resource_group.always_encrypted_sample.*.name[0]}"
89+
location = "${azurerm_resource_group.always_encrypted_sample.*.location[0]}"
90+
server_name = "${azurerm_sql_server.sql_server.*.name[0]}"
91+
edition = "Standard"
92+
create_mode = "Default"
93+
requested_service_objective_name = "S0"
94+
}
95+
96+
97+
resource "azurerm_app_service" "web_3" {
98+
name = "${var.resource_names["AppService"]}"
99+
resource_group_name = "${azurerm_resource_group.always_encrypted_sample.*.name[0]}"
100+
app_service_plan_id = "${azurerm_app_service_plan.always_encrypted_sample.id}"
101+
location = "${azurerm_resource_group.always_encrypted_sample.*.location[0]}"
102+
https_only = "true"
103+
app_settings = {
104+
APPINSIGHTS_INSTRUMENTATIONKEY = "${azurerm_application_insights.app_insights.instrumentation_key}"
105+
}
106+
site_config {
107+
default_documents = [
108+
"Default.htm",
109+
"Default.html",
110+
"Default.asp",
111+
"index.htm",
112+
"index.html",
113+
"iisstart.htm",
114+
"default.aspx",
115+
"index.php",
116+
"hostingstart.html",
117+
]
118+
http2_enabled = false //TODO: figure out if enabling this helps anything
119+
ftps_state = "Disabled"
120+
use_32_bit_worker_process = true
121+
}
122+
}
123+
124+
/*
125+
output "web_3_service_principle_id" {
126+
value = "${azurerm_app_service.web_3.identity.0.principal_id}"
127+
}
128+
*/
129+
130+
131+
resource "azurerm_key_vault" "always_encrypted_sample" {
132+
name = "${azurerm_resource_group.always_encrypted_sample.*.name[0]}"
133+
resource_group_name = "${var.resource_names["ResourceGroup"]}"
134+
location = "${azurerm_resource_group.always_encrypted_sample.*.location[0]}"
135+
tenant_id = "${data.azurerm_client_config.current.tenant_id}"
136+
sku {
137+
name = "standard"
138+
}
139+
140+
access_policy {
141+
tenant_id = "${data.azurerm_client_config.current.tenant_id}"
142+
object_id = "${var.certificate_creator}"
143+
144+
certificate_permissions = [
145+
"create", "get" # Terraform needs get to make the cert, probably to check its existance
146+
]
147+
}
148+
}
149+
150+
output "key_vault_uri" {
151+
value = "${azurerm_key_vault.always_encrypted_sample.vault_uri}"
152+
}
153+
154+
resource "azurerm_key_vault_certificate" "column_certificate" {
155+
name = "${var.resource_names["ColumnCertificate"]}"
156+
key_vault_id = "${azurerm_key_vault.always_encrypted_sample.id}"
157+
158+
certificate_policy {
159+
issuer_parameters {
160+
name = "Self"
161+
}
162+
163+
key_properties {
164+
exportable = false
165+
key_size = 4096
166+
key_type = "RSA"
167+
reuse_key = true #TODO: Can I make this false?
168+
}
169+
170+
#TODO We might want to auto renew if we are crazy.
171+
/*
172+
lifetime_action {
173+
action {
174+
action_type = "AutoRenew"
175+
}
176+
177+
trigger {
178+
days_before_expiry = 30
179+
}
180+
}
181+
*/
182+
secret_properties {
183+
content_type = "application/x-pkcs12"
184+
}
185+
186+
x509_certificate_properties {
187+
extended_key_usage = [
188+
"1.3.6.1.5.5.8.2.2",
189+
"1.3.6.1.4.1.311.10.3.1"
190+
]
191+
192+
key_usage = [
193+
"dataEncipherment",
194+
]
195+
196+
subject_alternative_names {
197+
dns_names = ["${azurerm_sql_server.sql_server.fully_qualified_domain_name}"]
198+
}
199+
200+
subject = "${var.certificate_cn}"
201+
validity_in_months = 12
202+
}
203+
}
204+
}

0 commit comments

Comments
 (0)