Skip to content

Commit

Permalink
feat: Include Terraform infrastructure provisioning
Browse files Browse the repository at this point in the history
  • Loading branch information
notheotherben committed Mar 4, 2023
1 parent 2b5afa6 commit c43b5f4
Show file tree
Hide file tree
Showing 9 changed files with 400 additions and 2 deletions.
6 changes: 4 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ updates:
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: .github/workflows
schedule:
interval: daily
open-pull-requests-limit: 5
- package-ecosystem: terraform
directory: "/infra"
schedule:
interval: daily
37 changes: 37 additions & 0 deletions infra/dns.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
resource "azurerm_dns_cname_record" "production" {
name = var.name
resource_group_name = "dns"
zone_name = var.domain
ttl = 300
record = azurerm_linux_function_app.production.default_hostname
}

resource "azurerm_dns_txt_record" "production-validation" {
name = "asuid.${var.name}"
resource_group_name = "dns"
zone_name = var.domain
ttl = 300

record {
value = azurerm_linux_function_app.production.custom_domain_verification_id
}
}

resource "azurerm_dns_cname_record" "staging" {
name = "${var.name}-staging"
resource_group_name = "dns"
zone_name = var.domain
ttl = 300
record = azurerm_linux_function_app.staging.default_hostname
}

resource "azurerm_dns_txt_record" "staging-validation" {
name = "asuid.${var.name}-staging"
resource_group_name = "dns"
zone_name = var.domain
ttl = 300

record {
value = azurerm_linux_function_app.staging.custom_domain_verification_id
}
}
146 changes: 146 additions & 0 deletions infra/function.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
resource "azurerm_service_plan" "function" {
name = "${var.name}-serviceplan"
location = azurerm_resource_group.function.location
resource_group_name = azurerm_resource_group.function.name
os_type = "Linux"
sku_name = "Y1"
}

data "azurerm_linux_function_app" "production" {
name = "${var.name}-sierrasoftworks"
resource_group_name = azurerm_resource_group.function.name
}

resource "azurerm_linux_function_app" "production" {
name = "${var.name}-sierrasoftworks"
location = azurerm_resource_group.function.location
resource_group_name = azurerm_resource_group.function.name
service_plan_id = azurerm_service_plan.function.id
storage_account_name = azurerm_storage_account.function.name
storage_account_access_key = azurerm_storage_account.function.primary_access_key

https_only = true

site_config {
http2_enabled = true
websockets_enabled = true

cors {
allowed_origins = var.allowed_origins
}

application_stack {
use_custom_runtime = true
}
}

identity {
type = "SystemAssigned"
}

app_settings = merge(
data.azurerm_linux_function_app.production.app_settings,
{
"OTEL_EXPORTER_OTLP_ENDPOINT" = "https://api.honeycomb.io",
"OTEL_EXPORTER_OTLP_HEADERS" = "x-honeycomb-team=${var.honeycomb-key-production}",
"OTEL_SERVICE_NAME" = "${var.name}",
"HONEYCOMB_KEY" = "${var.honeycomb-key-production}",
"HONEYCOMB_DATASET" = "${honeycombio_dataset.dataset.name}",
},
var.app-settings
)
}

resource "azurerm_app_service_custom_hostname_binding" "production" {
hostname = "${var.name}.${var.domain}"
app_service_name = azurerm_linux_function_app.production.name
resource_group_name = azurerm_resource_group.function.name

lifecycle {
ignore_changes = [ssl_state, thumbprint]
}

depends_on = [
azurerm_dns_txt_record.production-validation
]
}

resource "azurerm_app_service_managed_certificate" "production" {
custom_hostname_binding_id = azurerm_app_service_custom_hostname_binding.production.id
}

resource "azurerm_app_service_certificate_binding" "production" {
hostname_binding_id = azurerm_app_service_custom_hostname_binding.production.id
certificate_id = azurerm_app_service_managed_certificate.production.id
ssl_state = "SniEnabled"
}


data "azurerm_linux_function_app" "staging" {
name = "${var.name}-sierrasoftworks-staging"
resource_group_name = azurerm_resource_group.function.name
}

resource "azurerm_linux_function_app" "staging" {
name = "${var.name}-sierrasoftworks-staging"
location = azurerm_resource_group.function.location
resource_group_name = azurerm_resource_group.function.name
service_plan_id = azurerm_service_plan.function.id
storage_account_name = azurerm_storage_account.function.name
storage_account_access_key = azurerm_storage_account.function.primary_access_key

https_only = true

site_config {
http2_enabled = true
websockets_enabled = true

cors {
allowed_origins = var.allowed_origins
}

application_stack {
use_custom_runtime = true
}
}

identity {
type = "SystemAssigned"
}

app_settings = merge(
data.azurerm_linux_function_app.staging.app_settings,
{
"OTEL_EXPORTER_OTLP_ENDPOINT" = "https://api.honeycomb.io",
"OTEL_EXPORTER_OTLP_HEADERS" = "x-honeycomb-team=${var.honeycomb-key-staging}",
"OTEL_SERVICE_NAME" = "${var.name}"
"HONEYCOMB_KEY" = "${var.honeycomb-key-staging}",
"HONEYCOMB_DATASET" = "${honeycombio_dataset.dataset.name}",
},
var.app-settings
)
}

resource "azurerm_app_service_custom_hostname_binding" "staging" {
hostname = "${var.name}-staging.${var.domain}"
app_service_name = azurerm_linux_function_app.staging.name
resource_group_name = azurerm_resource_group.function.name

lifecycle {
ignore_changes = [ssl_state, thumbprint]
}

depends_on = [
azurerm_dns_txt_record.staging-validation
]
}

resource "azurerm_app_service_managed_certificate" "staging" {
custom_hostname_binding_id = azurerm_app_service_custom_hostname_binding.staging.id
}

resource "azurerm_app_service_certificate_binding" "staging" {
hostname_binding_id = azurerm_app_service_custom_hostname_binding.staging.id
certificate_id = azurerm_app_service_managed_certificate.staging.id
ssl_state = "SniEnabled"
}
85 changes: 85 additions & 0 deletions infra/github-actions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
data "azurerm_subscription" "current" {
}

resource "azuread_application" "deploy-production" {
display_name = "deploy.${var.name}.production"
owners = [data.azuread_client_config.current.object_id]
sign_in_audience = "AzureADMyOrg"
}

resource "azuread_service_principal" "deploy-production" {
application_id = azuread_application.deploy-production.application_id
app_role_assignment_required = false
owners = [
data.azuread_client_config.current.object_id,
]
}

resource "azuread_application" "deploy-staging" {
display_name = "deploy.${var.name}.staging"
owners = [data.azuread_client_config.current.object_id]
sign_in_audience = "AzureADMyOrg"
}

resource "azuread_service_principal" "deploy-staging" {
application_id = azuread_application.deploy-staging.application_id
app_role_assignment_required = false
owners = [
data.azuread_client_config.current.object_id,
]
}

resource "azuread_application_federated_identity_credential" "production" {
application_object_id = azuread_application.deploy-production.object_id
display_name = "Environment"
description = "Allows deployments from GitHub Actions to the 'Production' environment."
audiences = ["api://AzureADTokenExchange"]
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:${var.repository}:environment:${var.production-environment}"
}

resource "azuread_application_federated_identity_credential" "staging" {
application_object_id = azuread_application.deploy-staging.object_id
display_name = "Environment"
description = "Allows deployments from GitHub Actions to the 'Staging' environment."
audiences = ["api://AzureADTokenExchange"]
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:${var.repository}:environment:${var.staging-environment}"
}

resource "azuread_application_federated_identity_credential" "prs" {
application_object_id = azuread_application.deploy-staging.object_id
display_name = "PRs"
description = "Allows deployments from GitHub Actions for pull requests."
audiences = ["api://AzureADTokenExchange"]
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:${var.repository}:pull_request"
}

resource "azurerm_role_assignment" "deploy-production" {
scope = azurerm_linux_function_app.production.id
principal_id = azuread_service_principal.deploy-production.object_id
role_definition_name = "Contributor"
}

resource "azurerm_role_assignment" "deploy-staging" {
scope = azurerm_linux_function_app.staging.id
principal_id = azuread_service_principal.deploy-staging.object_id
role_definition_name = "Contributor"
}

output "deploy-production" {
value = {
tenant_id = data.azuread_client_config.current.tenant_id
subscription_id = data.azurerm_subscription.current.subscription_id
client_id = azuread_application.deploy-production.application_id
}
}

output "deploy-staging" {
value = {
tenant_id = data.azuread_client_config.current.tenant_id
subscription_id = data.azurerm_subscription.current.subscription_id
client_id = azuread_application.deploy-staging.application_id
}
}
55 changes: 55 additions & 0 deletions infra/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// We retrieve information on the client deploying this plan
// to determine tenant information.
data "azuread_client_config" "current" {}

variable "location" {
description = "The Azure location where this app will be deployed."
default = "North Europe"
}

variable "domain" {
description = "The domain root at which the app will be accessible."
default = "sierrasoftworks.com"
}

variable "name" {
description = "The name of the application being deployed."
default = "bender"
}

variable "repository" {
description = "The name of the GitHub repository that contains the application."
default = "SierraSoftworks/bender"
}

variable "production-environment" {
description = "The name of the production environment."
default = "Production"
}

variable "staging-environment" {
description = "The name of the staging environment."
default = "Staging"
}

variable "app-settings" {
description = "The application settings that should be configured for the function app."
type = map(string)
default = {
"FUNCTIONS_WORKER_RUNTIME" = "custom"
}
}

variable "honeycomb-key-staging" {
description = "The Honeycomb API key that should be used for staging."
}

variable "honeycomb-key-production" {
description = "The Honeycomb API key that should be used for production."
}

variable "allowed_origins" {
description = "The origins that should be allowed to access the API."
type = set(string)
default = ["*"]
}
10 changes: 10 additions & 0 deletions infra/marker.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
resource "honeycombio_dataset" "dataset" {
name = var.name
description = "Bender's infrastructure has been updated to the latest version."
}

resource "honeycombio_marker" "deployment" {
message = "Applying updated Terraform configuration"
type = "deploy"
dataset = honeycombio_dataset.dataset.name
}
Loading

0 comments on commit c43b5f4

Please sign in to comment.