Skip to Content
Internal ScanningDeployAWSSecrets Management

Secrets Management

This guide explains how to securely handle sensitive credentials when deploying the Internal Scanner.

What Are Secrets?

The Internal Scanner requires credentials provided by Detectify:

SecretDescriptionWhere to Find
License KeyActivates your scanner instanceDetectify UI → Internal Scanning Agents
Connector API KeyAuthenticates with Detectify platformDetectify UI → Internal Scanning Agents
Registry CredentialsPulls scanner container imagesDetectify UI → Internal Scanning Agents

These credentials are generated by Detectify and have a validity period managed on Detectify’s side. They are static and do not rotate automatically.

Security Principle: Secrets should never exist in plaintext in version control, logs, or anywhere they could be accidentally exposed.

Choose the approach that fits your infrastructure:

ApproachBest For
KMS EncryptionMost deployments - encrypted secrets stored in version control
AWS Secrets ManagerOrganizations with centralized secrets management policies

Note: For initial local testing only, you can use a gitignored terraform.tfvars file as shown in the Terraform guide. However, you should set up proper secrets management before deploying to any shared environment.


Encrypt secrets with AWS KMS and store the encrypted file in version control. Terraform decrypts them automatically during deployment.

How It Works

Secrets are encrypted locally using AWS KMS and stored as a binary blob in version control. During deployment, Terraform decrypts them automatically using the aws_kms_secrets data source — credentials exist only in memory and are never written to disk.

Step 1: Create a KMS Key

Create a KMS key using the AWS CLI:

aws kms create-key --description "Internal Scanner secrets encryption" --region eu-west-1 aws kms create-alias --alias-name alias/internal-scanner-secrets --target-key-id YOUR_KEY_ID --region eu-west-1

Alternatively, use an existing KMS key — just note its alias for the next steps.

Step 2: Create Secrets Directory

mkdir -p secrets/

Step 3: Create Plaintext Secrets File

Create secrets/secrets.json:

{ "registry_username": "your-registry-username", "registry_password": "your-registry-password", "license_key": "your-license-key", "connector_api_key": "your-connector-api-key" }

Security: This file will be deleted after encryption. Never commit it.

Step 4: Create Encryption Script

Create secrets/encrypt.sh:

#!/bin/bash set -e # ============================================================ # CONFIGURATION - Update these values for your environment # ============================================================ KEY_ALIAS="alias/internal-scanner-secrets" REGION="eu-west-1" # AWS_PROFILE="your-profile" # Uncomment if using named profile # ============================================================ # File paths (no changes needed) # ============================================================ SECRETS_FILE="secrets.json" ENCRYPTED_FILE="secrets.encrypted" # Validate secrets file exists if [ ! -f "$SECRETS_FILE" ]; then echo "Error: $SECRETS_FILE not found" echo "" echo "Create it with this structure:" echo '{' echo ' "registry_username": "...", ' echo ' "registry_password": "...",' echo ' "license_key": "...",' echo ' "connector_api_key": "..."' echo '}' exit 1 fi # Validate JSON syntax if ! jq empty "$SECRETS_FILE" 2>/dev/null; then echo "Error: $SECRETS_FILE contains invalid JSON" exit 1 fi echo "Encrypting secrets with KMS..." echo " Key: $KEY_ALIAS" echo " Region: $REGION" # Encrypt aws kms encrypt \ --region "$REGION" \ ${AWS_PROFILE:+--profile "$AWS_PROFILE"} \ --key-id "$KEY_ALIAS" \ --plaintext "fileb://$SECRETS_FILE" \ --output text \ --query CiphertextBlob | base64 --decode > "$ENCRYPTED_FILE" echo "" echo "Encryption successful!" echo "" echo "Next steps:" echo " 1. Delete plaintext: rm $SECRETS_FILE" echo " 2. Commit encrypted: git add $ENCRYPTED_FILE"

Make executable and run:

chmod +x secrets/encrypt.sh cd secrets/ ./encrypt.sh

Step 5: Delete Plaintext and Commit

# Delete plaintext (required!) rm secrets.json # Commit encrypted file git add secrets.encrypted encrypt.sh git commit -m "Add encrypted scanner secrets"

Step 6: Configure Terraform Decryption

Create secrets.tf in your main Terraform directory:

#--------------------------------------------------------------- # Secrets Decryption #--------------------------------------------------------------- # Decrypts KMS-encrypted secrets at runtime. # The encrypted file is safe to store in version control. data "aws_kms_secrets" "scanner" { secret { name = "secrets_json" payload = filebase64("${path.module}/secrets/secrets.encrypted") } } locals { # Parse decrypted JSON secrets = jsondecode(data.aws_kms_secrets.scanner.plaintext["secrets_json"]) # Extract individual values for use in module registry_username = local.secrets["registry_username"] registry_password = local.secrets["registry_password"] license_key = local.secrets["license_key"] connector_api_key = local.secrets["connector_api_key"] }

Step 7: Use Decrypted Secrets in Module

Update main.tf:

module "internal_scanner" { source = "detectify/internal-scanning/aws" version = "~> 1.0" # ... network configuration ... # Secrets (decrypted at runtime) license_key = local.license_key connector_api_key = local.connector_api_key registry_username = local.registry_username registry_password = local.registry_password }

Step 8: Configure .gitignore

# Terraform state .terraform/ *.tfstate *.tfstate.* # Plaintext secrets - NEVER commit secrets/secrets.json *.auto.tfvars secrets.tfvars # Encrypted secrets - safe to commit !secrets/*/secrets.encrypted

Updating Secrets

To update a secret, decrypt the file, edit it, re-encrypt, and commit.

Create secrets/decrypt.sh for this workflow:

#!/bin/bash set -e REGION="eu-west-1" # AWS_PROFILE="your-profile" # Uncomment if using named profile ENCRYPTED_FILE="secrets.encrypted" DECRYPTED_FILE="secrets.json" if [ ! -f "$ENCRYPTED_FILE" ]; then echo "Error: $ENCRYPTED_FILE not found" exit 1 fi echo "Decrypting secrets..." aws kms decrypt \ --region "$REGION" \ ${AWS_PROFILE:+--profile "$AWS_PROFILE"} \ --ciphertext-blob "fileb://$ENCRYPTED_FILE" \ --output text \ --query Plaintext | base64 --decode > "$DECRYPTED_FILE" echo "Decrypted to: $DECRYPTED_FILE" echo "" echo "WARNING: Delete this file after editing!" echo " Run: rm $DECRYPTED_FILE"

AWS Secrets Manager

For organizations with centralized secrets management policies or teams that prefer not to store encrypted files in repositories.

Store Secrets

aws secretsmanager create-secret \ --name "internal-scanner" \ --description "Internal Scanner credentials" \ --secret-string '{ "registry_username": "your-registry-username", "registry_password": "your-registry-password", "license_key": "your-license-key", "connector_api_key": "your-connector-api-key" }'

Terraform Configuration

# secrets.tf data "aws_secretsmanager_secret_version" "scanner" { secret_id = "internal-scanner" } locals { secrets = jsondecode(data.aws_secretsmanager_secret_version.scanner.secret_string) registry_username = local.secrets["registry_username"] registry_password = local.secrets["registry_password"] license_key = local.secrets["license_key"] connector_api_key = local.secrets["connector_api_key"] }

IAM Permissions

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["secretsmanager:GetSecretValue"], "Resource": "arn:aws:secretsmanager:*:*:secret:internal-scanner/*" } ] }

For security best practices, see Security & Privacy.


Troubleshooting

”AccessDeniedException” during encryption

Cause: Your IAM user/role lacks kms:Encrypt permission.

Solution: Add an IAM policy granting kms:Encrypt and kms:DescribeKey on your KMS key to your IAM identity, or ensure you’re listed in the KMS key policy.

”AccessDeniedException” during terraform apply

Cause: Pipeline role lacks kms:Decrypt permission.

Solution:

  1. Verify the role ARN in your KMS key policy
  2. Check the IAM role has the decrypt policy attached
  3. Confirm you’re using the correct AWS region

”InvalidCiphertextException”

Cause: Encrypted file corrupted or encrypted with a different key.

Solution:

  1. Re-encrypt from the original plaintext
  2. Verify you’re using the same KMS key alias
  3. Check the file wasn’t modified after encryption

Terraform shows secrets in plan output

Cause: Variables not marked as sensitive = true.

Solution: Ensure all secret variables have sensitive = true in their definition:

variable "license_key" { type = string sensitive = true # This prevents display in logs }

Next Steps

Last updated on