Overview

BYOK Data Plane

Bring Your Own Key (BYOK) uses the same PromptQL-managed, single-tenant infrastructure as a Dedicated Data Plane, while encryption at rest is controlled by a customer-managed key.

What you need to do

  1. Choose AWS or GCP and confirm the Data Plane region with PromptQL.
  2. Create a customer-managed encryption key in that same region.
  3. Apply the documented key policy or IAM binding so PromptQL can provision encrypted resources.
  4. Provide the key ARN or resource name when creating the Data Plane.
  5. Keep the key enabled and preserve the required policy or IAM access while the Data Plane is active.

PromptQL then provisions and operates the Dedicated Data Plane using your key for encryption at rest. You own the key lifecycle, policy, and availability.

Treat revoking access to, disabling, deleting, or destroying an in-use customer-managed key as a non-recoverable action.

An Enterprise agreement is required. Contact sales to begin provisioning.

AWS

AWS prerequisites

  • Confirm the Enterprise deployment model and target AWS region with the PromptQL team.
  • Confirm the target region is enabled and has sufficient service quotas.
  • Record the Data Plane name, domain, availability-zone IDs, network CIDRs, and private-connectivity requirements.
  • BYOK requires a customer-managed AWS KMS key in the same region as the Data Plane.

AWS network and availability plan

  • Select one AWS region and at least two Availability Zones. Use AZ IDs such as use1-az1, not account-specific names such as us-east-1a.
  • Reserve a non-overlapping VPC CIDR. A /16 to /20 is recommended. If routable address space is constrained, AWS supports a /21 to /23 VPC CIDR when a separate /16 to /20 Pod IP CIDR is supplied.
  • Reserve a non-overlapping Kubernetes Service CIDR. If using a Pod IP CIDR, it must not overlap either the VPC or service CIDR.
  • Confirm the network path to each data source: VPC peering, Transit Gateway, VPN, PrivateLink, or another approved private path.

AWS customer tasks

  1. Confirm the AWS region for your Data Plane with PromptQL.
  2. Create a customer-managed KMS key in that same region.
  3. Apply the key policy below so PromptQL can create the required encryption grant.
  4. Paste the key ARN into the Customer-managed KMS Key ARN field and submit the Data Plane form.
  5. Keep the key enabled and preserve the required policy while the Data Plane is active.

PromptQL then provisions and operates the Dedicated Data Plane using your key for encryption at rest.

Detailed AWS setup

AWS setup requirements
  • AWS account with administrative access
  • AWS CLI installed and configured
  • AWS_REGION environment variable set to your desired region (e.g., export AWS_REGION=us-east-1)
Setup instructions
  1. Create a KMS key

    Create a symmetric encryption key in the same region as your Data Plane. A single key per region is used for all data-at-rest encryption in that region (S3 buckets and RDS in the primary region; EKS secrets per region).

    aws kms create-key \
      --region $AWS_REGION \
      --description "PromptQL customer-managed encryption key" \
      --key-usage ENCRYPT_DECRYPT \
      --origin AWS_KMS \
      --query 'KeyMetadata.{KeyId:KeyId,Arn:Arn}' \
      --output table
    

    Optionally, create an alias for easier identification:

    aws kms create-alias \
      --region $AWS_REGION \
      --alias-name alias/hasura-ddn-cmek \
      --target-key-id <key-id-from-above>
    
  2. Configure key policy

    Configure the key policy with three statements:

    • EnableIAMUserPermissions: grants management access to whoever should be able to administer this key. The example below uses your account root (arn:aws:iam::<YOUR_ACCOUNT_ID>:root), but you can replace the Principal with whichever IAM entity will manage the key: for example, your admin role (arn:aws:iam::<YOUR_ACCOUNT_ID>:role/<ADMIN_ROLE>) or admin user (arn:aws:iam::<YOUR_ACCOUNT_ID>:user/<ADMIN_USER>). Without this statement, no IAM principal can manage the key, which can lead to lockout.
    • AllowHasuraDDNCreateGrant: lets PromptQL create a KMS grant that delegates key access to your Data Plane account during provisioning. The kms:GrantOperations condition restricts the grant to only the operations required for data-at-rest encryption (Encrypt, Decrypt, GenerateDataKey, etc.): PromptQL cannot create a grant that includes destructive operations like ScheduleKeyDeletion.
    • AllowHasuraDDNDescribeKey: lets PromptQL read key metadata and list grants for visibility during provisioning. PromptQL does not retire or revoke grants on Data Plane teardown (see "Revoking access" below for what happens on destroy).

    Replace <YOUR_ACCOUNT_ID> with your AWS account ID.

Key policy JSON
{
  "Version": "2012-10-17",
  "Id": "hasura-ddn-cmek-policy",
  "Statement": [
    {
      "Sid": "EnableIAMUserPermissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<YOUR_ACCOUNT_ID>:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "AllowHasuraDDNCreateGrant",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::824267124885:role/HasuraDataPlaneAutomation"
      },
      "Action": "kms:CreateGrant",
      "Resource": "*",
      "Condition": {
        "ForAllValues:StringEquals": {
          "kms:GrantOperations": [
            "Encrypt",
            "Decrypt",
            "ReEncryptFrom",
            "ReEncryptTo",
            "GenerateDataKey",
            "GenerateDataKeyWithoutPlaintext",
            "DescribeKey",
            "CreateGrant",
            "RetireGrant"
          ]
        }
      }
    },
    {
      "Sid": "AllowHasuraDDNDescribeKey",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::824267124885:role/HasuraDataPlaneAutomation"
      },
      "Action": ["kms:DescribeKey", "kms:ListGrants"],
      "Resource": "*"
    }
  ]
}

Save the above as key-policy.json (replacing <YOUR_ACCOUNT_ID>) and apply it:

aws kms put-key-policy \
  --key-id <KEY_ID> \
  --policy-name default \
  --policy file://key-policy.json
AWS form value

Paste the full KMS key ARN into the Customer-managed KMS Key ARN field:

arn:aws:kms:<region>:<your-account-id>:key/<key-id>

The key must be in the same region as the Data Plane. A Data Plane is deployed in one region and may span multiple Availability Zones within that region.

Revoking access (AWS)

Impact of key revocation

Revoking, disabling, or deleting a customer-managed KMS key that is in use immediately impacts the Data Plane. Treat any of these key-state changes as a non-recoverable action. Storage and database access can fail, and affected resources may become permanently inaccessible. Do not rely on re-enabling the key as a recovery procedure.

Avoid this scenario

Do not revoke, disable, or delete a customer-managed key that is in use by a Data Plane. If you only need to temporarily cut off PromptQL's access, contact the PromptQL team before changing the key policy or grants so the change can be planned without making encrypted resources inaccessible.

What happens to the KMS grant when the Data Plane is destroyed

When you destroy a Data Plane, PromptQL does not retire or revoke the KMS grant that was created on your key. The grant remains on your key in a dormant state: the Data Plane account that was the grantee no longer has any resources using it, so the grant has no practical effect.

This is intentional: it makes Data Plane teardown resilient to any subsequent changes to your key policy. You don't need to keep kms:RetireGrant permissions in place for PromptQL indefinitely.

To remove the residual grant at your convenience:

# List grants on the key to find the grant ID
aws kms list-grants --key-id <KEY_ID> --region <KEY_REGION>

# Retire the grant from the Data Plane account (the grantee). Any IAM principal in
# that account can retire it. If the Data Plane account no longer exists, AWS will
# eventually clean up grants for closed accounts automatically.
aws kms retire-grant \
  --region <KEY_REGION> \
  --key-id <KEY_ARN> \
  --grant-id <GRANT_ID>

GCP

GCP prerequisites

  • Confirm the Enterprise deployment model and target GCP region with the PromptQL team.
  • Record the Data Plane name, domain, zones, network CIDR, and private-connectivity requirements.
  • BYOK requires a customer-managed Cloud KMS key in the same region as the Data Plane.

GCP network and availability plan

  • Select one GCP region and at least two zones.
  • Reserve a non-overlapping VPC CIDR, normally /16 to /20.
  • Confirm the network path to each data source: VPC Network Peering, VPN, Private Service Connect, or another approved private path.
  • For BYOC, use a dedicated GCP project and confirm organization policies and quotas permit the required GKE, Cloud SQL, storage, load-balancing, KMS, and networking resources.

GCP customer tasks

  1. Confirm the GCP region for your Data Plane with PromptQL.
  2. Create a Cloud KMS key ring and customer-managed key in that same region.
  3. Grant PromptQL's provisioning service account the key-scoped IAM access documented below.
  4. Paste the key resource name into the Customer-managed KMS Key Resource Name field and submit the Data Plane form.
  5. Keep the key enabled and preserve the required IAM access while the Data Plane is active.

PromptQL then provisions and operates the Dedicated Data Plane using your key for encryption at rest.

Detailed GCP setup

GCP setup requirements
  • GCP project with the Cloud KMS API enabled
  • gcloud CLI installed and authenticated as a project owner
  • GCP_REGION environment variable set to your desired region (e.g., export GCP_REGION=us-central1)
Apply the setup
  1. Create a key ring and KMS key

    Create the key ring and a symmetric encryption key in the same region as your Data Plane. A single key per region is used for all data-at-rest encryption in that region (GCS and Cloud SQL in the primary region; GKE etcd secrets per region).

    gcloud kms keyrings create hasura-ddn-cmek \
      --location=$GCP_REGION
    
    gcloud kms keys create hasura-ddn-cmek-key \
      --location=$GCP_REGION \
      --keyring=hasura-ddn-cmek \
      --purpose=encryption
    
  2. Grant PromptQL's provisioning service account access

    PromptQL needs three permissions on the key: read it, read its IAM policy, and add IAM bindings. During provisioning it can attach the Data Plane's Cloud SQL, GCS, and GKE service agents to your key.

    PromptQL provisioning service account:

    • Production: ddn-automation@hasura-ddn.iam.gserviceaccount.com

    We recommend using a custom role with only the three permissions PromptQL actually uses. This is the GCP equivalent of the least-privilege key policy on AWS.

    # Create a custom role at the project level (one-time per project).
    gcloud iam roles create hasuraDDNCMEKKeyAdmin \
      --project=$GCP_PROJECT \
      --title="PromptQL CMEK Key Admin" \
      --description="Lets PromptQL automation read and bind IAM on a single KMS key, nothing else." \
      --permissions=cloudkms.cryptoKeys.get,cloudkms.cryptoKeys.getIamPolicy,cloudkms.cryptoKeys.setIamPolicy \
      --stage=GA
    
    # Bind the custom role to PromptQL's service account, scoped to this key only.
    gcloud kms keys add-iam-policy-binding hasura-ddn-cmek-key \
      --location=$GCP_REGION \
      --keyring=hasura-ddn-cmek \
      --member="serviceAccount:ddn-automation@hasura-ddn.iam.gserviceaccount.com" \
      --role="projects/$GCP_PROJECT/roles/hasuraDDNCMEKKeyAdmin"
    

    With this custom role, PromptQL cannot disable, destroy, rotate, or otherwise modify the key: only read it and add the service-agent IAM bindings required for data-at-rest encryption.

Alternative: use the predefined `roles/cloudkms.admin`

If you'd rather skip creating a custom role, you can grant roles/cloudkms.admin scoped to the single key. This is broader than necessary (it also lets PromptQL update the key, schedule version destruction, etc.) but the scope is still limited to this one key, not the whole project.

gcloud kms keys add-iam-policy-binding hasura-ddn-cmek-key \
  --location=$GCP_REGION \
  --keyring=hasura-ddn-cmek \
  --member="serviceAccount:ddn-automation@hasura-ddn.iam.gserviceaccount.com" \
  --role="roles/cloudkms.admin"
GCP form value

Paste the full Cloud KMS resource name into the Customer-managed KMS Key Resource Name field:

projects/<your-project>/locations/<region>/keyRings/hasura-ddn-cmek/cryptoKeys/hasura-ddn-cmek-key

The key must be in the same location as the Data Plane. A Data Plane is deployed in one region and may span multiple zones within that region.

Revoking access (GCP)

Impact of key revocation

Revoking access to, disabling, or destroying a Cloud KMS key version that is in use immediately impacts the Data Plane. Treat any of these key-state changes as a non-recoverable action. Storage and database access can fail, and affected resources may become permanently inaccessible. Do not rely on restoring or re-enabling the key version as a recovery procedure.

Avoid this scenario

Do not revoke access to, disable, or destroy a Cloud KMS key version that is in use by a Data Plane. If you only need to temporarily cut off PromptQL's access, contact the PromptQL team before changing IAM bindings or key state so the change can be planned without making encrypted resources inaccessible.

What happens to the IAM bindings when the Data Plane is destroyed

When you destroy a Data Plane, PromptQL does not remove the IAM bindings it created on your key for the Cloud SQL, GCS, and GKE service agents. The bindings remain in place but are dormant: the Data Plane project that owned those service agents is gone, so the bindings have no practical effect.

This is intentional: teardown is resilient to any subsequent changes to your key's IAM policy. You don't need to keep cloudkms.cryptoKeys.setIamPolicy permissions in place for PromptQL indefinitely.

To remove the residual bindings at your convenience:

# 1. Inspect the IAM policy on the key
gcloud kms keys get-iam-policy hasura-ddn-cmek-key \
  --location=$GCP_REGION \
  --keyring=hasura-ddn-cmek

# 2. Remove each stale binding. Replace <NUMBER> with the data plane project's
#    project number (visible in the bindings from step 1). Three service agents
#    were granted access: Cloud SQL, GCS, and GKE: so remove all three:

# Cloud SQL service agent
gcloud kms keys remove-iam-policy-binding hasura-ddn-cmek-key \
  --location=$GCP_REGION \
  --keyring=hasura-ddn-cmek \
  --member="serviceAccount:service-<NUMBER>@gcp-sa-cloud-sql.iam.gserviceaccount.com" \
  --role="roles/cloudkms.cryptoKeyEncrypterDecrypter"

# GCS service agent (Cloud Storage)
gcloud kms keys remove-iam-policy-binding hasura-ddn-cmek-key \
  --location=$GCP_REGION \
  --keyring=hasura-ddn-cmek \
  --member="serviceAccount:service-<NUMBER>@gs-project-accounts.iam.gserviceaccount.com" \
  --role="roles/cloudkms.cryptoKeyEncrypterDecrypter"

# GKE / Compute Engine service agent (etcd application-layer secret encryption)
gcloud kms keys remove-iam-policy-binding hasura-ddn-cmek-key \
  --location=$GCP_REGION \
  --keyring=hasura-ddn-cmek \
  --member="serviceAccount:service-<NUMBER>@compute-system.iam.gserviceaccount.com" \
  --role="roles/cloudkms.cryptoKeyEncrypterDecrypter"

Azure

Customer-managed encryption keys for PromptQL-managed Dedicated Data Planes are not currently supported on Azure. Use Dedicated with PromptQL-managed encryption, or BYOC when the Data Plane and its cloud resources must run in your Azure subscription.