Skip to content

Latest commit

 

History

History
355 lines (270 loc) · 13.8 KB

File metadata and controls

355 lines (270 loc) · 13.8 KB

Configuring secure application delivery using Citrix ADC and the Venafi Provider for HashiCorp Terraform

In this example, we'll show you how to better secure application delivery using Venafi Provider for HashiCorp Terraform with your Citrix ADC instance. Adding Venafi enables you to manage certificates more securely as part of the TLS termination process on your load balancer.

Who should use this example?

The steps described in this example are typically performed by DevOps engineers or system administrators. Generally, you'll need a basic understanding of Citrix ADC, Venafi Trust Protection Platform or Venafi Cloud, and the required permissions for completing the tasks described in the example.

About this example

In this example, we use Terraform's infrastructure as code automation process with the Venafi Provider to generate and install certificates as part of SSL termination on an ADC (specifically, Citrix ADC) for load balancing web traffic. We'll also utilize three HTTP servers contained in a cluster as the endpoints that are sending and receiving web traffic and being managed by Citrix ADC.

Later in this example, you'll generate a certificate for demo-citrix.venafi.example using the Venafi Provider for Hashicorp Terraform with either Venafi Trust Protection Platform (TPP) or Venafi Cloud. Then after adding them to your Citrix ADC resources, you'll use them in the ADC node. And finally, you'll configure the service group members and bind them to your ADC node.

NOTE While we'll be using a Round robin balancing method in our ADC configuration, keep in mind that there are other methods that might be more suitable for your specific use case.

scenario

About retrieving a certificate using the Venafi Provider for Terraform

BEST PRACTICES In general, be careful when using self-signed certificates because of the inherent risks of no identity verification or trust control. The public and private keys are both held by the same entity. Also, self-signed certificates cannot be revoked; they can only be replaced. If an attacker has already gained access to a system, the attacker can spoof the identity of the subject. Of course, CAs can revoke a certificate only when they discover the compromise.

We'll be managing the following file structure:

./<your_workspace>/citrix_adc/
├── citrixadc-prereq.sh
├── citrix.tf
├── main.tf
├── venafi.tf
└── terraform.tfvars

We provided the needed files in this folder except for terraform.tfvars. The configuration of the file is customized by each user, which is why we provided terraform.tfvars.example for each Venafi platform that you could use for your own configuration.

Prerequisites

Before you continue, carefully review these prerequisites:

  • Verify that Terraform is installed correctly. Look here for installation details..
  • Verify that you have administrator access to your Citrix ADC instance.
  • Verify that you have administrator access to either Venafi Trust Protection Platform or Venafi Cloud Services.
  • If you're using Trust Protection Platform and you do NOT have administrator access, you'll need to generate an access token from the VCert CLI, as described in Trust between Terraform and Trust Protection Platform) in the Venafi Provider for HashiCorp Terraform README.
  • Verify that you have three (3) web servers that are running your application; for this example, we'll use NGINX servers.

Getting started

Here are the steps we'll complete as we go through this example:

  1. Create your Terraform variables file.
  2. Set up your main Terraform config file.
  3. Set up your Venafi Terraform config file.
  4. Set up your Citrix Terraform config file.
  5. Apply your setup.
  6. Test your implementation

NOTE These steps reflect an example Terraform file structure and apply only to this example. Of course, you might be able to use a similar configuration, depending on your needs and preferences.

Step 1: Create your Terraform variables file

The terraform.tfvars configuration for Citrix is divided into the following sections:

  • Platform configuration (Venafi Cloud or TPP)
  • Your Citrix management access
  • The configuration for your site
  • The Citrix Appliance where your data is stored
  • The Virtual IP and Port, which is the entry point for your traffic-management object of your virtual server
  • The service group members are physical nodes on the network (NGINX servers for this example)

First we have to set the following variables depending on your platform that you are working on:

NOTE You can check how to set these variables and the venafi_zone in here.

TPP:

tpp_url = "https://tpp.example"
bundle_path = "<bundle_path>"
access_token = "<access_token>"

Venafi Cloud:

venafi_api_key = "<venafi_api_key>"

And finally configure your Citrix infrastructure:

NOTE The values we use here are for illustration only; you should change them according to your own configuration.

venafi_zone = "<venafi_zone>"

citrix_address = "192.168.x.x"
citrix_username = "your_citrix_user"
citrix_password = "your_password"

test_site_name = "demo-citrix"
test_site_domain = "venafi.example"

citrix_virtual_ip = "192.168.7.68"
citrix_virtual_port = "443"
citrix_service_group_members = [ "192.168.6.201:8001", "192.168.6.201:8002", "192.168.6.201:8003" ]

Step 2: Set up your main Terraform config file

  1. Declare that the Venafi and Citrix ADC providers are required:

    terraform {
        required_providers {
            venafi = {
                source = "venafi/venafi"
                version = "~> 0.11.2"
            }
            citrixadc = {
                source = "citrix/citrixadc"
                version = "~> 1.0.0"
            }
        }
        required_version = ">= 0.13"
    }
    
  2. Define you variables from terraforms.vars:

    TPP:

    variable "tpp_url" {
        type = string
    }
    
    variable "bundle_path" {
        type = string
    }
    
    variable "access_token" {
        type = string
    }
    

    Venafi Cloud:

    variable "venafi_api_key" {
        type = string
        sensitive = true
    }
    

    Then, define the following:

    variable "venafi_zone" {
        type = string
    }
    
    variable "test_site_name" {
        type = string
    }
    
    variable "test_site_domain" {
        type = string
    }
    
    variable "citrix_address" {
        type = string
    }
    
    variable "citrix_username" {
        type = string
    }
    
    variable "citrix_password" {
        type = string
    sensitive = true
    }
    
    variable "citrix_virtual_ip"{
        type = string
    }
    
    variable "citrix_virtual_port"{
        type = string
    }
    
    variable "citrix_service_group_members"{
        type = list(string)
    }
    

Step 3: Set up your Venafi Terraform config file

  1. Specify the connection and authentication settings for your Venafi provider:

    TPP:

    provider "venafi" {
        url          = var.tpp_url
        trust_bundle = file(var.bundle_path)
        access_token = var.access_token
        zone         = var.venafi_zone
    }
    

    Venafi Cloud:

    provider "venafi" {
        api_key = var.venafi_api_key
        zone = var.venafi_zone
    }
    
  2. Create a venafi_certificate resource that will generate a new key pair and enroll the certificate needed by a "tls_server" application:

    resource "venafi_certificate" "tls_server" {
        common_name = "${var.test_site_name}.${var.test_site_domain}"
        san_dns = [
            "${var.test_site_name}.${var.test_site_domain}"
        ]
        algorithm = "RSA"
        rsa_bits = 2048
        expiration_window = 720
    }
    

Step 4: Set up your Citrix ADC Terraform config file

  1. Specify your Citrix ADC provider configuration:

    provider "citrixadc" {
        endpoint = "https://${var.citrix_address}/"
        username = var.citrix_username
        password = var.citrix_password
        insecure_skip_verify = true
    }
    
  2. Set your Citrix ADC resources as it gets the content from the venafi_certificate resource:

    resource "citrixadc_systemfile" "my_certfile" {
        filename = "${venafi_certificate.tls_server.common_name}.cert"
        filelocation = "/nsconfig/ssl"
        filecontent = venafi_certificate.tls_server.certificate
    }
    
    resource "citrixadc_systemfile" "my_keyfile" {
        filename = "${venafi_certificate.tls_server.common_name}.key"
        filelocation = "/nsconfig/ssl"
        filecontent = venafi_certificate.tls_server.private_key_pem
    }
    
    resource "citrixadc_systemfile" "my_chainfile" {
        filename = "${var.test_site_name}_chain.cert"
        filelocation = "/nsconfig/ssl"
        filecontent = venafi_certificate.tls_server.chain
    }
    
    resource "citrixadc_sslcertkey" "my_chain" {
        certkey = "${var.test_site_name}_ca_chain"
        cert = "${citrixadc_systemfile.my_certfile.filelocation}/${citrixadc_systemfile.my_chainfile.filename}"
        bundle = "NO"
        expirymonitor = "DISABLED"
    }
    
  3. Create a resource to manage client SSL profiles on a Citrix to the ADC:

    resource "citrixadc_sslcertkey" "my_certkey" {
        certkey = "${var.test_site_name}.${var.test_site_domain}"
        cert = "${citrixadc_systemfile.my_certfile.filelocation}/${citrixadc_systemfile.my_certfile.filename}"
        key = "${citrixadc_systemfile.my_keyfile.filelocation}/${citrixadc_systemfile.my_keyfile.filename}"
        expirymonitor = "DISABLED"
        linkcertkeyname = citrixadc_sslcertkey.my_chain.certkey
    }
    
  4. Create your service group members resources to manage membership in pools:

    resource "citrixadc_servicegroup" "my_pool" {
        servicegroupname = "${var.test_site_name}_pool"
        servicetype = "HTTP"
        lbvservers = [citrixadc_lbvserver.my_virtual_server.name]
        servicegroupmembers = var.citrix_service_group_members
    }
    
  5. Create your resource in order to create your virtual server for managing your Citrix ADC:

    resource "citrixadc_lbvserver" "my_virtual_server" {
        name = "vs_${var.test_site_name}"
        ipv46 = var.citrix_virtual_ip
        port = var.citrix_virtual_port
        servicetype = "SSL"
        lbmethod = "ROUNDROBIN"
        sslcertkey = citrixadc_sslcertkey.my_certkey.certkey
        ciphersuites = ["DEFAULT"]
    }
    
  6. For verification purposes, output the certificate, private key, and chain in PEM format and as a PKCS#12 keystore (base64-encoded):

    output "my_private_key" {
        value = venafi_certificate.tls_server.private_key_pem
        sensitive = true
    }
    
    output "my_certificate" {
        value = venafi_certificate.tls_server.certificate
    }
    
    output "my_trust_chain" {
        value = venafi_certificate.tls_server.chain
    }
    
    output "my_p12_keystore" {
        value = venafi_certificate.tls_server.pkcs12
    }
    

Step 5: Apply your setup

Finally, run terraform init, terraform plan and terraform apply to apply your configuration changes. Then you should be able to log into your Citrix ADC appliance in 192.168.x.x using <your_citrix_user>:<your_password>.

If done correctly, you should see an output similar to the following:

asciicast

To tear down your infrastructure, execute terraform destroy, and then you should see an output similar to this:

asciicast

What's next

After you've successfully implemented this example, consider the following tips:

What happens when certificates expire? How do they get renewed? (click here to expand):

IMPORTANT! When your certificate expires, the chances that users of your application will experience an outage increases significantly. When an outage occures, most web browsers automatically warn users. Also, your ADC provider might turn off the appliances when any of the certificates of the appliances it points to expire (here's an example).

To renew a certificate, you'll need to generate a new CSR. Once the certificate is ready, the CA will deliver it to you. Then you can install it on your appliance.

How do certificates get validated? (click to expand)

Your application's web server sends a copy of the SSL certificate to the browser. The browser validates the certificate against a list of certificate authorities that are publicy trusted. The browser then returns a message indicating whether the certificate was signed by a trusted CA. Finally, the web server starts an SSL-encrypted session with the web browser. You can learn more about this here.