Consistent Security and performance across clouds using BIG-IP and Terraform
As reported by IDC, enterprises are increasingly considering deploying applications and services into multiple public clouds. This presents a new set of challenges: configuring virtual compute, storage, network, and middleware services on each of these clouds require cloud specific skills and configuration normalization to ensure same customer experience. In my previous blog, I went through how to configure BIG-IP as a part of your CICD pipeline using Terraform and GitHub Actions. As you might know BIG-IP Virtual Editions can be deployed in all major public cloud using Terraform. In this article, I will cover how to consistently apply configurations across BIG-IP Virtual Editions running in multi-cloud using Terraform Automation. We will use templating for AS3 and will build declarations that you can apply to BIG-IP running in any cloud using Terraform.
Environment
For this use case example, I will deploy a WAF policy on the BIG-IP devices running in AWS and Azure. BIG-IP VE instances and backend applications instances are created using the terraform scripts found here, but the following instructions will work on any cloud deployed BIG-IP VEs & applications.
I will use an AS3 declaration which will configure a new tenant on the BIG-IP with a virtual server, a pool, and nodes. I will apply the same declaration with an associated WAF policy to virtual BIG-IP instances in AWS and Azure clouds using Terraform.
Prerequisites
1. An AWS Account
2. An Azure Account
3. BIG-IP VE v14+ instance running on AWS and Azure
4. The ASM module is licensed and activated on your BIG-IP
5. Terraform installed on your local or remote jump box
Let’s get started…
AS3 Declaration
Below is an example of an AS3 declaration for creating a virtual server and attaching a WAF security policy to it. At a minimum, you will need to edit the IPs to match your environment.
{ "class": "AS3", "action": "deploy", "persist": true, "declaration": { "class": "ADC", "schemaVersion": "3.24.0", "id": "Protected_App", "My_Protected_App": { "class": "Tenant", "App": { "class": "Application", "template": "http", "serviceMain": { "class": "Service_HTTP", "virtualPort": 8080, "virtualAddresses": [ "10.2.1.200" ], "pool": "web_pool", "policyWAF": { "use": "My_ASM_Policy" }, "persistenceMethods": [], "profileMultiplex": { "bigip": "/Common/oneconnect" } }, "web_pool": { "class": "Pool", "monitors": [ "http" ], "members": [ { "servicePort": 80, "serverAddresses": [ "10.2.1.101", "10.2.1.102" ] } ] }, "My_ASM_Policy": { "class": "WAF_Policy", "url": "https://raw.githubusercontent.com/scshitole/more-terraform/master/Sample_app_sec_02_waf_policy.xml", "ignoreChanges": true } } } } }
Using Terraform to configure the BIG-IP
I am using terraform to deploy the AS3 declaration above, which configures the Virtual Server and attaches the ASM WAF policy. The WAF Policy URL is also declared in the AS3 as shown above.
The BIG-IP can be provisioned in Azure using the ‘terraform-Azure-bigip-module’ located at https://github.com/f5devcentral/terraform-azure-bigip-module. Once done, I use Terraform configuration below to deploy the secure application configuration using the bigip-as3 resource which is part of BIG-IP Terraform provider. Terraform configuration is located at https://github.com/scshitole/mcloud/blob/main/terraform-azure-bigip-module/examples/as3/main.tf
Example Terraform TF for Azure Cloud
provider "azurerm" { features {} } terraform { required_providers { bigip = { source = "f5networks/bigip" version = "1.8.0" } } } provider "bigip" { address = var.address username = "admin" password = var.password port = var.port } resource "bigip_as3" "as3-waf" { as3_json = file(var.declaration) } resource "azurerm_network_interface" "appnic" { count = var.app_count name = "app_nic" location = var.location resource_group_name = var.resource_group ip_configuration { name = "testConfiguration" subnet_id = var.subnet_id private_ip_address_allocation = "Static" private_ip_address = "10.2.1.101" } } resource "azurerm_managed_disk" "appdisk" { name = "datadisk_existing_${count.index}" count = var.app_count location = var.location resource_group_name = var.resource_group storage_account_type = "Standard_LRS" create_option = "Empty" disk_size_gb = "1023" } resource "azurerm_availability_set" "avset" { name = "avset" location = var.location resource_group_name = var.resource_group platform_fault_domain_count = 2 platform_update_domain_count = 2 managed = true } resource "azurerm_virtual_machine" "app" { count = var.app_count name = "app_vm_${count.index}" location = var.location availability_set_id = azurerm_availability_set.avset.id resource_group_name = var.resource_group network_interface_ids = [element(azurerm_network_interface.appnic.*.id, count.index)] vm_size = "Standard_DS1_v2" # Uncomment this line to delete the OS disk automatically when deleting the VM delete_os_disk_on_termination = true # Uncomment this line to delete the data disks automatically when deleting the VM delete_data_disks_on_termination = true storage_image_reference { publisher = "Canonical" offer = "UbuntuServer" sku = "16.04-LTS" version = "latest" } storage_os_disk { name = "myosdisk${count.index}" caching = "ReadWrite" create_option = "FromImage" managed_disk_type = "Standard_LRS" } # Optional data disks storage_data_disk { name = "datadisk_new_${count.index}" managed_disk_type = "Standard_LRS" create_option = "Empty" lun = 0 disk_size_gb = "1023" } storage_data_disk { name = element(azurerm_managed_disk.appdisk.*.name, count.index) managed_disk_id = element(azurerm_managed_disk.appdisk.*.id, count.index) create_option = "Attach" lun = 1 disk_size_gb = element(azurerm_managed_disk.appdisk.*.disk_size_gb, count.index) } os_profile { computer_name = format("appserver-%s", count.index) admin_username = "appuser" admin_password = var.upassword } os_profile_linux_config { disable_password_authentication = false } tags = { Name = "${var.prefix}-app" } }
Example Terraform TF for AWS Cloud
The BIG-IP can be deployed using the terraform module for AWS located at https://github.com/f5devcentral/terraform-aws-bigip, once done I am using the below TF configuration to deploy the application and the AS3 application objects using terraform BIG-IP provider resource bigip-as3 in AWS Cloud, this will also protect the application using the ASM WAF policy defined in the AS3. Terraform TF file configuration is located at https://github.com/scshitole/mcloud/blob/main/terraform-aws-bigip/examples/as3/main.tf
terraform { required_providers { bigip = { source = "f5networks/bigip" version = "1.8.0" } } } provider "bigip" { address = var.address username = "admin" password = var.password port= var.port } resource "bigip_as3" "as3-waf" { as3_json = file(var.declaration) } provider "aws" { profile = "default" region = "us-east-2" } data "aws_ami" "ubuntu" { most_recent = true filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] } filter { name = "virtualization-type" values = ["hvm"] } owners = ["099720109477"] # Canonical } resource "aws_instance" "example" { ami = data.aws_ami.ubuntu.id instance_type = "t2.micro" private_ip = "10.0.0.100" subnet_id = var.subnet_id tags = { Name = "scs-minstance" } }
Conclusion
With Terraform automation, BIG-IP and AS3 can facilitate consistent network, security and performance configurations for applications across multiple clouds, both public and private. As shown above, you can create and use the same AS3 declaration (same load balancing and WAF policy) for applications running in AWS and Azure. The AS3 template I showed can be customized for HTTP Services, TLS Encryption, Network Security, Application Security, DOS Protection etc.