curl -X GET "https://global.api.konghq.com/v2/cloud-gateways/provider-accounts?filter%5Bprovider%5D%5Beq%5D=aws" \
--no-progress-meter --fail-with-body \
-H "Authorization: Bearer $KONNECT_TOKEN"\
-H "Accept: application/json"\
-H "Content-Type: application/json"Flush a public Dedicated Cloud Gateway managed cache using Terraform
Deploy a konnect_gateway_custom_plugin_streaming custom plugin that authenticates to the managed cache via AWS STS and runs FLUSHDB, exposed through a konnect_gateway_service and konnect_gateway_route, then trigger a flush by calling the Terraform output URL.
Prerequisites
Terraform and the Konnect provider
This is a Konnect tutorial and requires a Konnect personal access token.
-
Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.
-
Export your token to an environment variable:
export KONNECT_TOKEN='YOUR_KONNECT_PAT' -
Create an
auth.tffile that configures thekong/konnectTerraform provider. Changeserver_urlif you are using a region other thanus:echo ' terraform { required_providers { konnect = { source = "kong/konnect" } konnect-beta = { source = "kong/konnect-beta" } } } provider "konnect" { server_url = "https://us.api.konghq.com" } provider "konnect-beta" { server_url = "https://us.api.konghq.com" } ' > auth.tf -
Next, initialize your project and download the provider:
terraform init
The provider automatically uses the KONNECT_TOKEN environment variable if it is available. If you would like to use a custom authentication token, set the personal_access_token field alongside server_url in the provider block.
An AWS managed cache
This tutorial requires an AWS managed cache attached to a ready public Dedicated Cloud Gateway control plane with a live data plane.
If you don’t have one configured yet, create one with Terraform.
You need to retrieve the provider account ID.
First, make a GET request to the Konnect Cloud Gateways API using the /provider-accounts endpoint:
Export the id from the output as a Terraform variable:
export TF_VAR_provider_id='YOUR_PROVIDER_ACCOUNT_ID'Use the
idfrom the output, notprovider_account_id.
The supported region, availability zones, and CIDR blocks depend on your provider account. List the values that AWS supports from the availability endpoint:
curl -s -H "Authorization: Bearer $KONNECT_TOKEN" \
https://global.api.konghq.com/v2/cloud-gateways/availability.json | \
jq '.providers[] | select(.provider == "aws") | .regions[] | {region, availability_zones, cidr_blocks}'Use a supported region, its availability_zones, and a CIDR subnet inside one of the supported cidr_blocks in the following configuration, which creates the public network, the control plane, a live data plane on that network, and the managed cache:
echo '
variable "provider_id" {
type = string
}
resource "konnect_cloud_gateway_network" "my_cloudgatewaynetwork" {
name = "Terraform Network"
region = "us-east-2"
availability_zones = [
"use2-az1",
"use2-az2",
"use2-az3"
]
cidr_block = "10.0.0.0/16"
cloud_gateway_provider_account_id = var.provider_id
}
resource "konnect_gateway_control_plane" "test_cp" {
name = "CGW Control Plane"
cloud_gateway = true
}
resource "konnect_cloud_gateway_configuration" "test_cp_configuration" {
control_plane_id = konnect_gateway_control_plane.test_cp.id
control_plane_geo = "us"
api_access = "public"
version = "3.15"
dataplane_groups = [
{
provider = "aws"
region = "us-east-2"
cloud_gateway_network_id = konnect_cloud_gateway_network.my_cloudgatewaynetwork.id
autoscale = {
configuration_data_plane_group_autoscale_autopilot = {
kind = "autopilot"
base_rps = 10
}
}
}
]
}
resource "konnect_cloud_gateway_addon" "managed_cache" {
name = "managed-cache"
owner = {
control_plane = {
control_plane_id = konnect_gateway_control_plane.test_cp.id
control_plane_geo = "us"
}
}
config = {
managed_cache = {
capacity_config = {
tiered = {
tier = "micro"
}
}
}
}
}
output "control_plane_id" {
value = konnect_gateway_control_plane.test_cp.id
}
' >> main.tfCreate the resources using Terraform:
terraform apply -auto-approveImportant: It can take 30-40 minutes for your network to initialize, and about 15 minutes after that for the managed cache to become ready. You must wait for both the network and the managed cache to show as
Readybefore continuing.
For sizing recommendations or a full walkthrough, see Configure an AWS managed cache for a Dedicated Cloud Gateway control plane or Configure an AWS managed cache for a Dedicated Cloud Gateway control plane group.
This how-to is for Dedicated Cloud Gateways with a public network since it uses the control plane endpoint to flush the cache.
Upload the custom plugin
This how-to deploys a custom Kong plugin that exposes a flush endpoint on your gateway.
Calling the endpoint authenticates to the managed cache with AWS STS-derived credentials and runs FLUSHDB, so you (or your CI/CD pipeline) can flush the cache without engineering involvement.
First, create and configure the custom plugin:
-
Create a
schema.luafile that defines the plugin’s configuration fields.echo ' local typedefs = require "kong.db.schema.typedefs" return { name = "cache-flusher", fields = { { protocols = typedefs.protocols_http }, { config = { type = "record", fields = { { host = typedefs.host({ default = "127.0.0.1", referenceable = true }) }, { port = typedefs.port({ default = 6379, referenceable = true }) }, { username = { type = "string", referenceable = true } }, { ssl = { type = "boolean", default = true } }, { server_name = { type = "string", referenceable = true } }, { cloud_authentication = { type = "record", fields = { { auth_provider = { type = "string", referenceable = true } }, { aws_region = { type = "string", referenceable = true } }, { aws_assume_role_arn = { type = "string", referenceable = true } }, { aws_cache_name = { type = "string", referenceable = true } }, } }}, } }, }, }, } ' > schema.lua -
Create a
handler.luafile that authenticates to the managed cache and runs the flush.echo ' local AWS = require "resty.aws" local redis = require "resty.redis" local aws_config = require "resty.aws.config" local AWS_DEFAULT_ROLE_SESSION_NAME = "KongElasticacheSession" local AWS_global_config = aws_config.global local aws = AWS({ region = AWS_global_config.region }) local plugin = { PRIORITY = 980, VERSION = "1.0.0", } local function get_aws_auth_token(conf, cloud_auth) local cachename = cloud_auth.aws_cache_name local name = conf.username local region = cloud_auth.aws_region local assume_role_arn = cloud_auth.aws_assume_role_arn local credentials = aws.config.credentials local sts, err = aws:STS({ region = region, credentials = credentials, stsRegionalEndpoints = AWS_global_config.sts_regional_endpoints, }) if not sts then return nil, err end local creds = aws:ChainableTemporaryCredentials { params = { RoleArn = assume_role_arn, RoleSessionName = AWS_DEFAULT_ROLE_SESSION_NAME, }, sts = sts, } local cache = aws:ElastiCache({ region = region }) local signer = cache:Signer { cachename = cachename, username = name, is_serverless = false, region = region, credentials = creds, } local auth_token, token_err = signer:getAuthToken() if token_err then return nil, token_err end return auth_token end local function get_auth_token(conf) local cloud_auth = conf.cloud_authentication local provider = cloud_auth.auth_provider if provider == "aws" then return get_aws_auth_token(conf, cloud_auth) end return nil, "cloud provider " .. tostring(provider) .. " not implemented" end function plugin:access(conf) kong.log.notice("[cache-flusher] starting cache flush") -- Connect to Cache kong.log.notice("[cache-flusher] connecting to Cache at ", conf.host, ":", conf.port) local red = redis:new() local ok, err = red:connect(conf.host, conf.port, { ssl = conf.ssl, ssl_verify = conf.ssl, server_name = conf.server_name, }) if not ok then kong.log.err("[cache-flusher] failed to connect to Cache: ", err) return kong.response.error(500, "cache flush failed: Cache connect error") end kong.log.notice("[cache-flusher] connected to Cache, obtaining auth token") -- Authenticate with STS-derived token local auth_token, token_err = get_auth_token(conf) if not auth_token then kong.log.err("[cache-flusher] failed to obtain auth token: ", token_err) return kong.response.error(500, "cache flush failed: auth token error") end kong.log.notice("[cache-flusher] auth token obtained, authenticating with Cache") local res, auth_err = red:auth(conf.username, auth_token) if not res then kong.log.err("[cache-flusher] failed to authenticate with Cache: ", auth_err) return kong.response.error(500, "cache flush failed: Cache auth error") end kong.log.notice("[cache-flusher] authenticated, flushing Cache") -- Flush Cache local flush_res, flush_err = red:flushdb("ASYNC") if not flush_res then kong.log.err("[cache-flusher] failed to flush Cache: ", flush_err) return kong.response.error(500, "cache flush failed: Cache flushdb error") end kong.log.notice("[cache-flusher] cache flush completed successfully") return kong.response.exit(200, { message = "[cache-flusher] cache flushed" }) end return plugin ' > handler.lua -
Declare the variables this how-to uses, and export the ones only you know:
echo ' variable "control_plane_id" { type = string } variable "flush_path" { type = string default = "/konnect/managed-cache/flush" } variable "ip_allowlist" { type = list(string) default = [] } variable "auto_flush" { type = bool default = false } variable "proxy_hostname" { type = string } ' > variables.tfIf you created your control plane as part of the prereqs, get its ID directly from Terraform state:
export TF_VAR_control_plane_id=$(terraform output -raw control_plane_id)Otherwise, export the ID of your existing control plane:
export TF_VAR_control_plane_id="your-control-plane-id" -
Look up the Konnect proxy hostname for your control plane, and export it as a Terraform variable:
CONTROL_PLANE_DETAILS=$(curl -X GET "https://us.api.konghq.com/v2/control-planes/$TF_VAR_control_plane_id" \ --no-progress-meter --fail-with-body \ -H "Authorization: Bearer $KONNECT_TOKEN" ) -
Export the proxy hostname:
PROXY_HOSTNAME=$(echo $CONTROL_PLANE_DETAILS | jq -r '.config.control_plane_endpoint | sub("https://";"") | split(".")[0]') export TF_VAR_proxy_hostname="${PROXY_HOSTNAME}.gateways.konggateway.com" -
Define the custom plugin, the Gateway Service and Route that expose the flush endpoint, and the plugin instance:
echo ' resource "konnect_gateway_custom_plugin_streaming" "cache_flusher" { control_plane_id = var.control_plane_id name = "cache-flusher" schema = file("${path.module}/schema.lua") handler = file("${path.module}/handler.lua") } resource "konnect_gateway_service" "cache_flusher_service" { control_plane_id = var.control_plane_id name = "managed-cache-flush-service" host = "127.0.0.1" port = 443 protocol = "https" } resource "konnect_gateway_route" "cache_flusher_route" { control_plane_id = var.control_plane_id service = { id = konnect_gateway_service.cache_flusher_service.id } paths = [var.flush_path] } resource "konnect_gateway_custom_plugin" "cache_flusher_instance" { name = "cache-flusher" control_plane_id = var.control_plane_id enabled = true service = { id = konnect_gateway_service.cache_flusher_service.id } route = { id = konnect_gateway_route.cache_flusher_route.id } config = { "cloud_authentication" : { "auth_provider" : "{vault://env/ADDON_MANAGED_CACHE_AUTH_PROVIDER}", "aws_assume_role_arn" : "{vault://env/ADDON_MANAGED_CACHE_AWS_ASSUME_ROLE_ARN}", "aws_cache_name" : "{vault://env/ADDON_MANAGED_CACHE_AWS_CACHE_NAME}", "aws_region" : "{vault://env/ADDON_MANAGED_CACHE_AWS_REGION}" }, "host" : "{vault://env/ADDON_MANAGED_CACHE_HOST}", "port" : "{vault://env/ADDON_MANAGED_CACHE_PORT}", "server_name" : "{vault://env/ADDON_MANAGED_CACHE_SERVER_NAME}", "ssl" : true, "username" : "{vault://env/ADDON_MANAGED_CACHE_USERNAME}" } depends_on = [konnect_gateway_custom_plugin_streaming.cache_flusher] } ' >> main.tfThe
{vault://env/ADDON_MANAGED_CACHE_*}references are populated automatically by Konnect once your managed cache add-on reaches a Ready state, so you don’t need to configure any AWS IAM credentials yourself. -
Add an output for the flush URL:
echo ' output "flush_proxy_url" { value = "https://${var.proxy_hostname}${var.flush_path}" } ' > output.tf -
Apply the configuration:
terraform apply -auto-approveYou’ll get a response like the following:
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
Strongly recommended: Restrict access and auto-flush on apply
Use the following sections to further configure the managed cache flush behavior.
Limit IPs that can trigger a flush
If you want to limit which IPs can trigger a flush, set ip_allowlist to a list of IPs or CIDRs, and add an ip-restriction plugin scoped to the flush route.
-
Configure the IP Restriction plugin:
echo ' resource "konnect_gateway_plugin_ip_restriction" "ip-restriction-plugin" { count = length(var.ip_allowlist) > 0 ? 1 : 0 config = { allow = var.ip_allowlist message = "NOT ALLOWED" status = 405 } control_plane_id = var.control_plane_id enabled = true service = { id = konnect_gateway_service.cache_flusher_service.id } route = { id = konnect_gateway_route.cache_flusher_route.id } } ' >> main.tf -
Export the IPs you want to allow list:
export TF_VAR_ip_allowlist='["203.0.113.0/24"]' -
Apply the Terraform configuration:
terraform apply -auto-approve
Requests from IPs outside the allowlist receive a 405 response.
Automatically flush on terraform apply
-
If you want the cache to flush automatically every time you run
terraform apply, setauto_flushtotrue:echo ' resource "terraform_data" "flush_cache" { count = var.auto_flush ? 1 : 0 triggers_replace = [timestamp()] provisioner "local-exec" { command = "sleep 10 && curl -sf https://${var.proxy_hostname}${var.flush_path}" } depends_on = [ konnect_gateway_route.cache_flusher_route, konnect_gateway_custom_plugin.cache_flusher_instance, konnect_gateway_plugin_ip_restriction.ip-restriction-plugin, ] } ' >> main.tf -
Export the auto flush behavior:
export TF_VAR_auto_flush=true -
Apply the Terraform configuration:
terraform apply -auto-approve
When
auto_flushistrue, everyterraform applytriggers a cache flush, not just the first one. Subsequent applies also show theterraform_data.flush_cacheresource being destroyed and recreated. This is expected and can be safely ignored.
Validate
Trigger a flush by calling the URL Terraform output in the previous step:
curl -sf "$(terraform output -raw flush_proxy_url)"A successful flush returns:
{"message": "[cache-flusher] cache flushed"}Cleanup
Remove the flush endpoint
To remove the flush endpoint and all associated resources:
terraform destroyFAQs
How do I flush a managed cache for a private Dedicated Cloud Gateway?
This how-to is scoped to Dedicated Cloud Gateways with a public network, because the flush endpoint is reached through the control plane endpoint. A private network Dedicated Cloud Gateway doesn’t have a control plane endpoint to route through.
Instead, reach the flush endpoint through the FQDN assigned to the private IP address of your Dedicated Cloud Gateway, for example through a CDN or nodes placed in front of the data planes, or over your internal/private network. As long as a client can reach that FQDN, the rest of this how-to (the custom plugin, Terraform resources, and flush call) applies the same way.