Skip to content

Guide: Blindfold Secret Management Functions

This guide walks you through using F5XC Blindfold functions to securely encrypt sensitive data. By the end, you’ll understand how to:

  • Encrypt TLS private keys - Secure certificate key storage
  • Protect cloud credentials - AWS, Azure, and GCP secrets
  • Secure container registries - Private image pull authentication
  • Understand the security model - Local encryption, never transmitted unencrypted

F5 Distributed Cloud Secret Management (“blindfold”) provides client-side encryption for sensitive data. The blindfold functions encrypt your secrets locally using RSA-OAEP with SHA-256, meaning your plaintext secrets never leave your machine unencrypted.

┌─────────────────────────────────────────────────────────────────────┐
│ Your Local Machine │
│ │
│ ┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐ │
│ │ Secret │───►│ Blindfold │───►│ Encrypted │ │
│ │ (plaintext) │ │ Function │ │ Ciphertext │ │
│ └──────────────┘ │ (RSA-OAEP) │ └────────┬────────┘ │
│ └────────┬─────────┘ │ │
│ │ │ │
│ ┌────────▼─────────┐ │ │
│ │ F5XC Public Key │ │ │
│ │ (fetched once) │ │ │
│ └──────────────────┘ │ │
└──────────────────────────────────────────────────────│────────────┘
┌─────────────────────────┐
│ F5 Distributed Cloud │
│ (stores ciphertext │
│ only) │
└─────────────────────────┘
  • Local encryption: Secrets encrypted on your machine before transmission
  • RSA-OAEP with SHA-256: Industry-standard encryption algorithm
  • Policy-controlled decryption: Only authorized F5XC services can decrypt
  • No plaintext storage: F5XC never receives or stores plaintext secrets

Before you begin, ensure you have:

Configure one of these authentication methods via environment variables:

Section titled “Option 1: API Token (Recommended for development)”
Terminal window
export F5XC_API_URL="https://your-tenant.console.ves.volterra.io"
export F5XC_API_TOKEN="your-api-token"
Section titled “Option 2: P12 Certificate (Recommended for production)”
Terminal window
export F5XC_API_URL="https://your-tenant.console.ves.volterra.io"
export F5XC_P12_FILE="/path/to/your-credentials.p12"
export F5XC_P12_PASSWORD="your-p12-password" # pragma: allowlist secret

-> Tip: Add these to your shell profile (~/.bashrc or ~/.zshrc) for persistence across terminal sessions.

Terminal window
git clone https://GitHub.com/robinmordasiewicz/terraform-provider-f5xc.git
cd terraform-provider-f5xc/examples/guides/blindfold
Terminal window
cp terraform.tfvars.example terraform.tfvars

Edit terraform.tfvars to enable the examples you want to test:

# Enable the TLS certificate example
enable_certificate_example = true
# Namespace configuration
namespace_name = "example-blindfold-test"
create_namespace = true

Step 3: Generate Test Certificates (for certificate example)

Section titled “Step 3: Generate Test Certificates (for certificate example)”
Terminal window
openssl req -x509 -newkey rsa:2048 \
-keyout certs/server.key \
-out certs/server.crt \
-days 365 -nodes \
-subj "/CN=example.com"
Terminal window
terraform init
terraform plan
terraform apply

Review the plan output, then type yes to confirm deployment.

  1. Check the Terraform outputs for created resource names
  2. Navigate to the F5XC Console
  3. Verify the certificate shows encrypted private key (not plaintext)

The provider includes two blindfold functions:

Encrypts base64-encoded plaintext:

provider::f5xc::blindfold(plaintext, policy_name, namespace)
ParameterTypeDescription
plaintextstringbase64-encoded secret to encrypt
policy_namestringName of the SecretPolicy
namespacestringNamespace containing the policy

Example:

location = provider::f5xc::blindfold(
base64encode(var.my_secret),
"ves-io-allow-volterra",
"shared"
)

Reads a file and encrypts its contents:

provider::f5xc::blindfold_file(path, policy_name, namespace)
ParameterTypeDescription
pathstringPath to the file to encrypt
policy_namestringName of the SecretPolicy
namespacestringNamespace containing the policy

Example:

location = provider::f5xc::blindfold_file(
"${path.module}/certs/server.key",
"ves-io-allow-volterra",
"shared"
)

Every F5XC tenant includes a default policy: ves-io-allow-volterra in the shared namespace. This policy allows Volterra (F5XC) services to decrypt secrets.

Store TLS certificates for load balancers. Note that TLS private keys are typically too large (>1000 bytes) for direct blindfold encryption (~190 byte limit). Use clear_secret_info for TLS keys:

resource "f5xc_certificate" "example" {
name = "example-certificate"
namespace = "shared"
certificate_url = "string:///${base64encode(file("${path.module}/certs/server.crt"))}"
# TLS private keys are too large for blindfold encryption
# Use clear_secret_info - the key is transmitted securely over HTTPS
private_key {
clear_secret_info {
url = "string:///${base64encode(file("${path.module}/certs/server.key"))}"
}
}
use_system_defaults {}
}

~> Size Limitation: Blindfold encryption uses RSA-OAEP which limits plaintext to ~190 bytes. TLS private keys exceed this limit. Use clear_secret_info for certificates - the data is transmitted securely over HTTPS. For secrets under 190 bytes (API keys, passwords), use blindfold functions as shown below.

Protect AWS secret access keys for VPC site deployments:

resource "f5xc_cloud_credentials" "aws" {
name = "aws-credentials"
namespace = "system"
aws_secret_key {
access_key = var.aws_access_key_id
secret_key {
blindfold_secret_info {
location = provider::f5xc::blindfold(
base64encode(var.aws_secret_access_key),
"ves-io-allow-volterra",
"shared"
)
}
}
}
}

Secure Azure service principal client secrets:

resource "f5xc_cloud_credentials" "Azure" {
name = "Azure-credentials"
namespace = "system"
azure_client_secret {
subscription_id = var.azure_subscription_id
tenant_id = var.azure_tenant_id
client_id = var.azure_client_id
client_secret {
blindfold_secret_info {
location = provider::f5xc::blindfold(
base64encode(var.azure_client_secret),
"ves-io-allow-volterra",
"shared"
)
}
}
}
}

Encrypt GCP service account JSON key files:

resource "f5xc_cloud_credentials" "gcp" {
name = "gcp-credentials"
namespace = "system"
gcp_cred_file {
credential_file {
blindfold_secret_info {
location = provider::f5xc::blindfold_file(
var.gcp_credentials_file,
"ves-io-allow-volterra",
"shared"
)
}
}
}
}

Protect container registry passwords for private image pulls:

resource "f5xc_container_registry" "example" {
name = "Docker-registry"
namespace = "shared"
registry = "Docker.io"
user_name = var.registry_username
password {
blindfold_secret_info {
location = provider::f5xc::blindfold(
base64encode(var.registry_password),
"ves-io-allow-volterra",
"shared"
)
}
}
}

While the built-in ves-io-allow-volterra policy works for most cases, you can create custom policies for fine-grained access control:

locals {
policy_name = "example-custom-policy"
policy_ns = "example-namespace"
}
# Reference your custom policy
location = provider::f5xc::blindfold(
base64encode(var.secret),
local.policy_name,
local.policy_ns
)
variable "secrets" {
type = map(string)
default = {
"api-key" = "secret1"
"auth-token" = "secret2"
}
}
locals {
encrypted_secrets = {
for name, value in var.secrets :
name => provider::f5xc::blindfold(
base64encode(value),
"ves-io-allow-volterra",
"shared"
)
}
}

RSA-OAEP encryption has a maximum plaintext size based on the key size:

Key SizeMaximum Plaintext
2048-bit~190 bytes
4096-bit~446 bytes

~> Note: If your secret exceeds the size limit, consider splitting it or using a different approach. The function will return a clear error message if the plaintext is too large.

The blindfold functions return a sealed secret string with the string:/// prefix followed by a base64-encoded JSON structure:

string:///eyJrZXlfdmVyc2lvbiI6InYxLjIuMyIsInBvbGljeV9pZCI6InNoYXJlZC92ZXMtaW8tYWxsb3ctdm9sdGVycmEiLCJ0ZW5hbnQiOiJ5b3VyLXRlbmFudCIsImRhdGEiOiJBQkNERUYxMjM0NTY3ODkwLi4uIn0=

When base64-decoded, the sealed JSON contains these fields:

{
"key_version": "v1.2.3",
"policy_id": "shared/ves-io-allow-volterra",
"tenant": "your-tenant",
"data": "ABCDEF1234567890..."
}

Field descriptions:

  • key_version: Public key version used for encryption
  • policy_id: Reference to the SecretPolicy (namespace/name format)
  • tenant: Your F5XC tenant identifier
  • data: base64-encoded RSA-OAEP ciphertext
  • Idempotent: Same input produces different output (due to random padding)
  • Network required: Functions fetch the public key from F5XC API
  • Caching: Public keys are cached for the Terraform run

Symptom: Error message about missing authentication configuration.

Solution:

Terminal window
# Verify environment variables are set
echo $F5XC_API_URL
echo $F5XC_API_TOKEN # or F5XC_P12_FILE
# Set them if missing
export F5XC_API_URL="https://your-tenant.console.ves.volterra.io"
export F5XC_API_TOKEN="your-api-token"

Symptom: Error about secret policy not found.

Solutions:

  1. Use the built-in policy:

    policy_name = "ves-io-allow-volterra"
    namespace = "shared"
  2. Verify your custom policy exists in F5XC Console

Symptom: Error indicating plaintext exceeds maximum size.

Solutions:

  1. Verify your secret size:

    Terminal window
    wc -c < your-secret-file
  2. For large files (like some GCP credentials), consider:

    • Extracting only the private key portion
    • Using F5XC’s external secret management integration

Symptom: Error about file not found when using blindfold_file().

Solutions:

  1. Use ${path.module} for relative paths:

    location = provider::f5xc::blindfold_file(
    "${path.module}/certs/server.key", # Correct
    ...
    )
  2. Verify the file exists and is readable

Symptom: Error about invalid base64 encoding.

Solution: Ensure you’re base64-encoding your plaintext:

# Correct
location = provider::f5xc::blindfold(
base64encode(var.secret), # base64encode() wraps the secret
...
)
# Incorrect
location = provider::f5xc::blindfold(
var.secret, # Raw secret will fail
...
)

To remove all resources created by this guide:

Terminal window
terraform destroy

Type yes to confirm destruction.

!> Warning: This will immediately remove all created resources. Ensure you have backups of any certificates or credentials you need.

Now that you understand blindfold encryption, explore related resources: