dev: finally get the previewering working, I think

This commit is contained in:
Peter Williams 2023-04-23 18:42:42 -04:00
Родитель dd7a64d11e
Коммит 4ddff68b45
3 изменённых файлов: 199 добавлений и 8 удалений

Просмотреть файл

@ -1,4 +1,23 @@
# The backend database and API service for the Constellations web app.
#
# Because the MongoDB is isolated on a private network, the usual Azure admin
# systems do not work. However, with the bastion host setup defined in
# `constellations-bastion.tf`, it is possible to administer the database
# locally.
#
# 1. First, set up the bastion and SSH into it.
# 2. Forward a port to the DB:
# ```
# ssh -O forward -L 10255:wwtdev-cxbe-server.mongo.cosmos.azure.com:10255 wwt@wwtdevcxb.westus.cloudapp.azure.com
# ```
# 3. Make a temporary connection string, replacing the `...cosmos.azure.com` hostname
# with `localhost`. You can get the connection string from the database's admin
# page in the Azure Portal.
# 4. Connect using pymongo with some special settings:
# ```
# conn = pymongo.MongoClient(cs, tlsAllowInvalidCertificates=True, directConnection=True)
# ```
# where `cs` is the temporary connection string.
resource "azurerm_resource_group" "cx_backend" {
name = "${var.prefix}-cxbackend"

Просмотреть файл

@ -0,0 +1,102 @@
# A bastion host for the Constellations VPN so that we can see if things are
# actually working.
#
# To create the bastion, uncomment everything and generate an SSH key:
#
# `ssh-keygen -t rsa -b 4096 -C "wwt@cxbastion" -f bastion_rsa`
#
# Connect with:
#
# ```
# ssh -oIdentitiesOnly=yes -oPubkeyAcceptedAlgorithms=+ssh-rsa
# -i bastion_rsa wwt@wwtdevcxb.westus.cloudapp.azure.com
# ```
#
# Then see, e.g. the header comment in `constellations-previewer.tf` for some
# hints about how to admin the previewer.
resource "azurerm_subnet" "cx_bastion" {
name = "${var.prefix}-cxbastion"
resource_group_name = azurerm_resource_group.cx_backend.name
virtual_network_name = azurerm_virtual_network.cx_backend.name
address_prefixes = ["10.0.220.0/24"]
}
resource "azurerm_public_ip" "cx_bastion" {
name = "${var.prefix}-cxbastion"
resource_group_name = azurerm_resource_group.cx_backend.name
location = azurerm_resource_group.cx_backend.location
allocation_method = "Static"
domain_name_label = "${var.prefix}cxb"
lifecycle {
create_before_destroy = true
}
}
resource "azurerm_network_interface" "cx_bastion" {
name = "${var.prefix}-cxbastion"
location = azurerm_resource_group.cx_backend.location
resource_group_name = azurerm_resource_group.cx_backend.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.cx_bastion.id
private_ip_address_allocation = "Dynamic"
public_ip_address_id = azurerm_public_ip.cx_bastion.id
}
}
resource "azurerm_linux_virtual_machine" "cx_bastion" {
name = "${var.prefix}-cxbastion"
computer_name = "cxbastion"
resource_group_name = azurerm_resource_group.cx_backend.name
location = azurerm_resource_group.cx_backend.location
size = "Standard_B1ls"
admin_username = "wwt"
network_interface_ids = [
azurerm_network_interface.cx_bastion.id
]
admin_ssh_key {
username = "wwt"
public_key = file("bastion_rsa.pub")
}
os_disk {
name = "osdisk"
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "RedHat"
offer = "RHEL"
sku = "83-gen2"
version = "latest"
}
}
resource "azurerm_network_security_group" "cx_bastion" {
name = "${var.prefix}-cxbastion"
location = azurerm_resource_group.cx_backend.location
resource_group_name = azurerm_resource_group.cx_backend.name
security_rule {
name = "SSH"
priority = 1001
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "22"
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
resource "azurerm_network_interface_security_group_association" "cx_bastion" {
network_interface_id = azurerm_network_interface.cx_bastion.id
network_security_group_id = azurerm_network_security_group.cx_bastion.id
}

Просмотреть файл

@ -1,16 +1,48 @@
# The previewer microservice for the Constellations web app.
#
# For now (?) we are piggybacking on the app service plan for the main backend
# app, and the vnet subnet for the Mongo DB.
# The setup is complicated, perhaps more complicated than it needs to be. The
# fundamental issue is that we want this web app to not be publicly available;
# it should only be accessible from our VPN.
#
# - To make that be the case, we need to associate it with a "private endpoint"
# - But, it seems that in order for it to be able to communicate with the
# MongoDB, the app also needs to be assigned to a "delegated" vnet subnet.
# - Azure "app service plans" have a limit of two vnets associations per
# service, and the backend/keycloak plan has one for each of those. So this
# needs to be on its own plan.
# - Private endpoints are associated with subnets, but can't be associated with
# delegated subnets. So the app lives on two different subnets.
#
# That last piece makes me feel like I'm doing something wrong, but I haven't
# been able to figure out a better setup.
#
# Because the app only provides a private endpoint, much of the standard Azure
# tooling does not work, or does not work conveniently. As far as I can tell, to
# do much of anything we need to set up a bastion host (see
# `constellations-bastion.tf`) and do stuff in the terminal. To look at logs:
#
# ```
# curl 'https://$wwtdev-cxpv:(pwd)@wwtdev-cxpv.scm.azurewebsites.net/api/logs/docker/zip' --output docker.zip
# curl 'https://$wwtdev-cxpv:(pwd)@wwtdev-cxpv.scm.azurewebsites.net/api/logstream'
# ```
#
# Here, you can get the username/password from the deployment center settings of
# webhook URL. Manually trigger Docker update:
#
# ```
# curl -X POST 'https://$wwtdev-cxpv:(pwd)@wwtdev-cxpv.scm.azurewebsites.net/api/registry/webhook'
# ```
#
# etc.
resource "azurerm_linux_web_app" "cx_previewer" {
name = "${var.prefix}-cxpv"
location = azurerm_resource_group.cx_backend.location
resource_group_name = azurerm_resource_group.cx_backend.name
service_plan_id = azurerm_service_plan.cx_backend.id
service_plan_id = azurerm_service_plan.cx_previewer.id
app_settings = {
"AZURE_COSMOS_CONNECTIONSTRING" = azurerm_cosmosdb_account.cx_backend.connection_strings[0]
"MONGO_CONNECTION_STRING" = azurerm_cosmosdb_account.cx_backend.connection_strings[0]
"AZURE_STORAGE_CONNECTION_STRING" = azurerm_storage_account.constellations.primary_connection_string
"NUXT_PUBLIC_API_URL" = "https://api.${var.tld}"
"DOCKER_REGISTRY_SERVER_URL" = "https://index.docker.io/v1"
@ -27,6 +59,44 @@ resource "azurerm_linux_web_app" "cx_previewer" {
docker_image_tag = "latest"
}
}
virtual_network_subnet_id = azurerm_subnet.cx_previewer.id
logs {
detailed_error_messages = false
failed_request_tracing = false
http_logs {
file_system {
retention_in_days = 0
retention_in_mb = 35
}
}
}
}
resource "azurerm_service_plan" "cx_previewer" {
name = "${var.prefix}-cxpv"
resource_group_name = azurerm_resource_group.cx_backend.name
location = azurerm_resource_group.cx_backend.location
os_type = "Linux"
sku_name = "P1v2"
}
resource "azurerm_subnet" "cx_previewer" {
name = "${var.prefix}-cxpv"
resource_group_name = azurerm_resource_group.cx_backend.name
virtual_network_name = azurerm_virtual_network.cx_backend.name
address_prefixes = ["10.0.10.0/24"]
delegation {
name = "dlg-appServices"
service_delegation {
name = "Microsoft.Web/serverFarms"
actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
}
}
}
resource "azurerm_private_endpoint" "cx_previewer" {
@ -65,10 +135,10 @@ resource "azurerm_private_dns_a_record" "cx_previewer_server" {
zone_name = azurerm_private_dns_zone.cx_previewer.name
resource_group_name = azurerm_resource_group.cx_backend.name
ttl = 10
records = ["10.0.0.6"]
records = [azurerm_private_endpoint.cx_previewer.private_service_connection[0].private_ip_address]
tags = {
"creator" = "created by private endpoint wwtdev-cxpvEndpoint with resource guid 6af9f47a-2a22-43b5-9ecb-6c7525a28895"
"creator" = "created by private endpoint wwtdev-cxpvEndpoint with resource guid bcaa592e-a1be-48ea-8b79-6e9b121ec461"
}
}
@ -77,9 +147,9 @@ resource "azurerm_private_dns_a_record" "cx_previewer_server_scm" {
zone_name = azurerm_private_dns_zone.cx_previewer.name
resource_group_name = azurerm_resource_group.cx_backend.name
ttl = 10
records = ["10.0.0.6"]
records = [azurerm_private_endpoint.cx_previewer.private_service_connection[0].private_ip_address]
tags = {
"creator" = "created by private endpoint wwtdev-cxpvEndpoint with resource guid 6af9f47a-2a22-43b5-9ecb-6c7525a28895"
"creator" = "created by private endpoint wwtdev-cxpvEndpoint with resource guid bcaa592e-a1be-48ea-8b79-6e9b121ec461"
}
}