Skip to content

Latest commit

 

History

History

x-l4xlb-mtls

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Apigee X with an External L4 Load Balancer and Client Authentication (mTLS)

This sample provides a envoy-based managed instance group behind an external load balancer that can terminate mutual TLS (mTLS) to authenticate API clients.

Preparation

This example assumes that you have TLS credentials for the server as well as the clients available and set their path in the .tfvars file.

To try it out you can create a set of self signed certs:

mkdir -p ./certs && cd ./certs
openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout server-ca.key -x509 -days 3650 -outform PEM -out server-ca.crt -subj "/CN=Test Server CA"
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=test.api.example.com"
openssl x509 -req -in server.csr -CA server-ca.crt -CAkey server-ca.key -set_serial 100 -days 365 -outform PEM -out server.crt

openssl req -newkey rsa:2048 -nodes -keyform PEM -keyout client-ca.key -x509 -days 3650 -outform PEM -out client-ca.crt -subj "/CN=Test Client CA"
openssl genrsa -out example-client.key 2048
openssl req -new -key example-client.key -out example-client.csr -subj "/CN=Test Client"
openssl x509 -req -in example-client.csr -CA client-ca.crt -CAkey client-ca.key -set_serial 101 -days 365 -outform PEM -out example-client.crt
cd ..

And reference them in your tf.vars

ca_cert_path  = "./certs/client-ca.crt"
tls_cert_path = "./certs/server.crt"
tls_key_path  = "./certs/server.key"

Important Note:

Ensure that your tf variables file (.apigee_envgroups.test.hostnames[]) contains the same hostname as you used in the CN of your certificate.

Setup Instructions

Set the project ID where you want your Apigee Organization to be deployed to:

PROJECT_ID=my-project-id
cd samples/... # Sample from above
cp ./x-demo.tfvars ./my-config.tfvars

Decide on a backend and create the necessary config. To use a backend on Google Cloud Storage (GCS) use:

gsutil mb "gs://$PROJECT_ID-tf"

cat <<EOF >terraform.tf
terraform {
  backend "gcs" {
    bucket  = "$PROJECT_ID-tf"
    prefix  = "terraform/state"
  }
}
EOF

Validate your config:

terraform init
terraform plan --var-file=./my-config.tfvars -var "project_id=$PROJECT_ID"

and provision everything (takes roughly 25min):

terraform apply --var-file=./my-config.tfvars -var "project_id=$PROJECT_ID"

Testing

If you used a hostname for which you don't have a DNS entry you can use:

INGRESS_IP=$(gcloud compute addresses describe apigee-external --global --format="get(address)")
curl https://test.api.example.com/my-proxy --resolve test.api.example.com:443:$INGRESS_IP --cert ./certs/example-client.crt --key ./certs/example-client.key --cacert ./certs/server-ca.crt -v

Otherwise use:

curl https://my-domain.com/my-proxy --cert ./certs/example-client.crt --key ./certs/example-client.key --cacert ./certs/server-ca.crt -v

Providers

Name Version
google n/a

Modules

Name Source Version
apigee-x-core ../../modules/apigee-x-core n/a
apigee-x-mtls-mig ../../modules/apigee-x-mtls-mig n/a
mig-l4xlb ../../modules/l4xlb n/a
nip-development-hostname ../../modules/nip-development-hostname n/a
project github.com/terraform-google-modules/cloud-foundation-fabric//modules/project v28.0.0
vpc github.com/terraform-google-modules/cloud-foundation-fabric//modules/net-vpc v28.0.0

Resources

Name Type
google_compute_firewall.allow_xlb_hc resource

Inputs

Name Description Type Default Required
apigee_envgroups Apigee Environment Groups.
map(object({
hostnames = list(string)
}))
null no
apigee_environments Apigee Environments.
map(object({
display_name = optional(string)
description = optional(string)
node_config = optional(object({
min_node_count = optional(number)
max_node_count = optional(number)
}))
iam = optional(map(list(string)))
envgroups = list(string)
type = optional(string)
}))
null no
apigee_instances Apigee Instances (only one instance for EVAL orgs).
map(object({
region = string
ip_range = string
environments = list(string)
}))
null no
ax_region GCP region for storing Apigee analytics data (see https://cloud.google.com/apigee/docs/api-platform/get-started/install-cli). string n/a yes
billing_account Billing account id. string null no
ca_cert_path Path to User CA Cert File (pem). string n/a yes
exposure_subnets Subnets for exposing Apigee services.
list(object({
name = string
ip_cidr_range = string
region = string
secondary_ip_range = map(string)
}))
[] no
network VPC name. string n/a yes
network_tags mTLS proxy network tags list(string)
[
"apigee-mtls-proxy"
]
no
peering_range Peering CIDR range string n/a yes
project_create Create project. When set to false, uses a data source to reference existing project. bool false no
project_id Project id (also used for the Apigee Organization). string n/a yes
project_parent Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. string null no
support_range Support CIDR range of length /28 (required by Apigee for troubleshooting purposes). string n/a yes
tls_cert_path Path to Server Cert File (pem). string n/a yes
tls_key_path Path to Server Key File (pem). string n/a yes

Outputs

Name Description
nip_hostnames Map of envgroup name -> hostnames.