Skip to content

Instantly share code, notes, and snippets.

@lawrencegripper
Last active September 28, 2023 19:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lawrencegripper/294ae913feff17315f7bb08d382a577d to your computer and use it in GitHub Desktop.
Save lawrencegripper/294ae913feff17315f7bb08d382a577d to your computer and use it in GitHub Desktop.
Azure VPN Gateway OpenVPN
resource "random_string" "random" {
length = 8
special = false
upper = false
number = false
}
resource "azurerm_public_ip" "vpn_ip" {
name = "vpn-ip"
location = var.region
resource_group_name = var.resource_group_name
domain_name_label = random_string.random.result
allocation_method = "Dynamic"
tags = var.tags
}
resource "tls_private_key" "example" {
algorithm = "RSA"
rsa_bits = "2048"
}
# Create the root certificate
resource "tls_self_signed_cert" "ca" {
key_algorithm = tls_private_key.example.algorithm
private_key_pem = tls_private_key.example.private_key_pem
# Certificate expires after 1 year
validity_period_hours = 8766
# Generate a new certificate if Terraform is run within three
# hours of the certificate's expiration time.
early_renewal_hours = 200
# Allow to be used as a CA
is_ca_certificate = true
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
"client_auth",
"cert_signing"
]
dns_names = [ azurerm_public_ip.vpn_ip.domain_name_label ]
subject {
common_name = "CAOpenVPN"
organization = "dev env"
}
}
resource "local_file" "ca_pem" {
filename = "caCert.pem"
content = tls_self_signed_cert.ca.cert_pem
}
resource "null_resource" "cert_encode" {
provisioner "local-exec" {
# Bootstrap script called with private_ip of each node in the clutser
command = "openssl x509 -in caCert.pem -outform der | base64 -w0 > caCert.der"
}
depends_on = [ local_file.ca_pem ]
}
data "local_file" "ca_der" {
filename = "caCert.der"
depends_on = [
null_resource.cert_encode
]
}
resource "tls_private_key" "client_cert" {
algorithm = "RSA"
rsa_bits = "2048"
}
resource "tls_cert_request" "client_cert" {
key_algorithm = tls_private_key.client_cert.algorithm
private_key_pem = tls_private_key.client_cert.private_key_pem
# dns_names = [ azurerm_public_ip.vpn_ip.domain_name_label ]
subject {
common_name = "ClientOpenVPN"
organization = "dev env"
}
}
resource "tls_locally_signed_cert" "client_cert" {
cert_request_pem = tls_cert_request.client_cert.cert_request_pem
ca_key_algorithm = tls_private_key.example.algorithm
ca_private_key_pem = tls_private_key.example.private_key_pem
ca_cert_pem = tls_self_signed_cert.ca.cert_pem
validity_period_hours = 43800
allowed_uses = [
"key_encipherment",
"digital_signature",
"server_auth",
"key_encipherment",
"client_auth",
]
}
resource "azurerm_virtual_network_gateway" "vpn-gateway" {
name = "vpn-gateway"
location = var.region
resource_group_name = var.resource_group_name
type = "Vpn"
active_active = false
enable_bgp = false
sku = "VpnGw1"
ip_configuration {
name = "vnetGatewayConfig"
public_ip_address_id = azurerm_public_ip.vpn_ip.id
private_ip_address_allocation = "Dynamic"
subnet_id = azurerm_subnet.yoursubnethere.id
}
vpn_client_configuration {
address_space = ["10.1.0.0/16"]
vpn_client_protocols = ["OpenVPN"]
root_certificate {
name = "terraformselfsignedder"
public_cert_data = data.local_file.ca_der.content
}
}
}
output "client_cert" {
value = tls_locally_signed_cert.client_cert.cert_pem
}
output "client_key" {
value = tls_private_key.client_cert.private_key_pem
}
output "vpn_id" {
value = azurerm_virtual_network_gateway.vpn-gateway.id
}
#!/bin/bash
set -e
# Get vars from TF State
VPN_ID=`terraform output vpn_id`
VPN_CLIENT_CERT=`terraform output client_cert`
VPN_CLIENT_KEY=`terraform output client_key`
# Replace newlines with \n so sed doesn't break
VPN_CLIENT_CERT="${VPN_CLIENT_CERT//$'\n'/\\n}"
VPN_CLIENT_KEY="${VPN_CLIENT_KEY//$'\n'/\\n}"
CONFIG_URL=`az network vnet-gateway vpn-client generate --ids $VPN_ID -o tsv`
wget $CONFIG_URL -O "vpnconfig.zip"
# Ignore complaint about backslash in filepaths
unzip -o "vpnconfig.zip" -d "./vpnconftemp"|| true
OPENVPN_CONFIG_FILE="./vpnconftemp/OpenVPN/vpnconfig.ovpn"
echo "Updating file $OPENVPN_CONFIG_FILE"
sed -i "s~\$CLIENTCERTIFICATE~$VPN_CLIENT_CERT~" $OPENVPN_CONFIG_FILE
sed -i "s~\$PRIVATEKEY~$VPN_CLIENT_KEY~g" $OPENVPN_CONFIG_FILE
cp $OPENVPN_CONFIG_FILE openvpn.ovpn
rm -r ./vpnconftemp
rm vpnconfig.zip
@omerfsen
Copy link

You must add

  triggers = {
    always_run = timestamp()
  }

block to https://gist.github.com/lawrencegripper/294ae913feff17315f7bb08d382a577d#file-main-tf-L63-L70 otherwise it will only run once and consecutive runs will not produce cer file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment