> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets

This document outlines how Tensor9 BYOC manages sensitive data (secrets) within your Infrastructure as Code (IaC) to ensure security and support various ownership models for the services your product relies on.

## Secret ownership models

Tensor9 BYOC distinguishes between two core models for managing secrets, based on who owns the external service or resource:

| Secret Type               | Definition                                                                        | Managed By                                                                                 | Visibility                                             | Example Use Case                                               |
| ------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------ | -------------------------------------------------------------- |
| Shared Secrets            | Used for external services the vendor owns and needs for the product to function. | The vendor (configured on the vendor's side and "tunneled" into the customer's appliance). | Customer may be able to view these secrets.            | Sentry.io token for vendor-owned monitoring.                   |
| Customer-Supplied Secrets | Used for external services the customer fully controls and is providing.          | The customer (configured within the appliance during setup).                               | Vendor has no visibility into the actual secret value. | MongoDB Atlas connection string for a customer-owned database. |

Vendors and customers must agree on the ownership of all external services and their associated secrets.

**Vendor Recommendation**: While Tensor9 BYOC supports customer-supplied secrets at
the infrastructure (Terraform) level, we strongly encourage migrating to
a runtime secret model where the vendor's application exposes an admin setting
page for the customer to provide optional secrets after initial setup. This
avoids requiring a new deployment for every secret change and makes secrets
easier to manage as optional.

## Terraform secret patterns

Tensor9 BYOC supports the following common industry patterns for integrating secrets into your Terraform configuration:

### 1. Runtime fetching via data source (recommended for external secrets)

This is the most common and recommended pattern for external services. Secrets are stored in an external secret store and retrieved during Terraform execution using a data block.

| Action    | Vendor Workflow                                                                                                                               |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Define    | Create a data block in your Terraform to reference the secret by name.                                                                        |
| Reference | Reference the data source's output (e.g., `data.aws_secretsmanager_secret_version.sentry.secret_string`) in your compute resource definition. |
| Storage   | Secrets are stored in the respective external system (e.g., AWS Secrets Manager, AWS SSM Parameter Store).                                    |

#### Important constraints:

* **Do not use ARNs**: Tensor9 BYOC does not support referencing secrets by Amazon Resource Name (ARN). Use name-based identifiers instead, as ARNs are absolute and may not be accessible from the customer side of the appliance.
* **Use a literal secret name**: Name the secret by the plain path it lives at in your own account (e.g., `prod/sentry/token`). Don't build the name from a variable. Tensor9 BYOC reads the name at compile time to identify the secret, and gives each install its own isolated copy on the appliance side, so you don't parameterize the path yourself.

### 2. Variable injection

Secrets are passed into the Terraform configuration as variables, typically injected via a CI/CD pipeline or `.tfvars` file.

| Action    | Vendor Workflow                                                               |
| --------- | ----------------------------------------------------------------------------- |
| Define    | Define a variable block with `sensitive = true` and `ephemeral = true`.       |
| Reference | Reference the variable (e.g., `var.db_password`) in your resource definition. |
| Storage   | The secret is passed directly as a value into the pipeline.                   |

**Important Constraint**: Tensor9 BYOC requires that injected variables contain the actual secret value, not a reference (like a Secrets Manager secret ID). If you need to pass a reference, use the Runtime Fetching (Data Source) pattern instead.

### 3. Platform/infrastructure generated passwords (no Tensor9 support needed)

This pattern is for secrets that are automatically generated and managed by the cloud provider or Terraform itself (e.g., a database master password created by AWS RDS). Since the secret is fully encapsulated within the IaC, no special Tensor9 BYOC annotation or transfer logic is required.

## Secret annotation and configuration

For the Runtime Fetching and Variable Injection patterns, you must explicitly tell Tensor9 BYOC which variables and data sources represent secrets and who owns them using a configuration file (via the tuning document or a separate JSON file).

Without this annotation, Tensor9 BYOC defaults all secret-holding data sources/variables to be Vendor-owned (Shared).

## Secret lifecycle and rotation

| Secret Type      | When Collected                                                 | Vendor Access                                                                                                     |
| ---------------- | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Shared Secrets   | When the vendor executes `tofu apply` on their compiled stack. | The vendor places the secret in their external secret store; Tensor9 BYOC fetches and copies it to the appliance. |
| Customer Secrets | During the customer's onboarding/setup process via the UI.     | The vendor never has access to the secret value.                                                                  |

Before deployment, Tensor9 BYOC performs a pre-flight check to validate that all configured secrets meet the requirements.

### Secret rotation

The process for rotating secrets depends on how the secret is referenced in your Terraform:

1. **If passing by Value**: If the secret value is directly embedded in a resource definition (e.g., `password = var.db_password`), an update to the secret will be detected by Terraform, and a normal build and apply (deployment) will update the resource.
2. **If passing by Reference**: If the infrastructure retrieves the secret by reference (e.g., a data source fetching from Secrets Manager), the infrastructure itself will not detect a change to the secret value.
   * **Vendor Action Required**: The vendor must trigger a refresh or a new deployment.
   * **Application Logic Required**: The application consuming the secret must have refresh logic built-in to periodically check for updated values.

For secrets managed via AWS Secrets Manager, Tensor9 BYOC supports the use of
rotation Lambda functions. The vendor's controller will copy the rotation Lambda
function to the appliance side. This Lambda must use the ARN passed
into it at runtime and must not rely on hardcoded ARNs or other references
that point to the vendor's original stack resources, since those will not resolve in the appliance.

## Secrets by origin stack type

The approach to managing secrets varies by origin stack type. All approaches share the same principle: **store secrets in AWS Secrets Manager or SSM Parameter Store, then pass them to your application as environment variables**.

### Terraform origin stacks

Define secrets in AWS Secrets Manager or SSM Parameter Store, then inject them into your compute resources as environment variables.

**Defining the secret**:

```terraform theme={null}
resource "aws_secretsmanager_secret" "db_password" {
  name = "prod/db/password"
}

resource "aws_secretsmanager_secret_version" "db_password" {
  secret_id     = aws_secretsmanager_secret.db_password.id
  secret_string = var.db_password
}
```

**Injecting into ECS Fargate**:

```terraform theme={null}
resource "aws_ecs_task_definition" "app" {
  family = "${var.namespace}myapp"

  container_definitions = jsonencode([
    {
      name  = "app"
      image = "myapp:latest"

      # Inject secret as environment variable
      secrets = [
        {
          name      = "DB_PASSWORD"
          valueFrom = aws_secretsmanager_secret.db_password.arn
        }
      ]
    }
  ])
}
```

**Injecting into Lambda**:

```terraform theme={null}
resource "aws_lambda_function" "api" {
  function_name = "${var.namespace}myapp-api"

  environment {
    variables = {
      DB_PASSWORD = data.aws_secretsmanager_secret_version.db_password.secret_string
    }
  }
}

data "aws_secretsmanager_secret_version" "db_password" {
  secret_id = aws_secretsmanager_secret.db_password.id
}
```

See [Terraform Origin Stacks](/byoc/origin-stack/terraform) for complete documentation.

### CloudFormation origin stacks

Use CloudFormation dynamic references to fetch secrets from Secrets Manager during stack deployment, then pass them to your resources.

```yaml theme={null}
Parameters:
  InstanceId:
    Type: String

Resources:
  # Secret in Secrets Manager
  DBPasswordSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: !Sub '${InstanceId}/prod/db/password'
      SecretString: !Ref DBPassword

  # ECS Task Definition with secret injection
  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: !Sub 'myapp-${InstanceId}'
      ContainerDefinitions:
        - Name: app
          Image: myapp:latest
          Secrets:
            - Name: DB_PASSWORD
              ValueFrom: !Ref DBPasswordSecret
```

See [CloudFormation Origin Stacks](/byoc/origin-stack/cloudformation) for complete documentation.

### Docker Compose origin stacks

Define secrets in the tuning document, then reference them as environment variables in your compose file.

**docker-compose.yml**:

```yaml theme={null}
services:
  api:
    image: myapp/api:latest
    environment:
      - DB_PASSWORD=${DB_PASSWORD}
      - API_KEY=${API_KEY}
```

**tuning.json**:

```json theme={null}
{
  "version": "V1",
  "secrets": {
    "db_password": {
      "source": "aws_secretsmanager",
      "secretId": "prod/db/password",
      "environmentVariable": "DB_PASSWORD"
    },
    "api_key": {
      "source": "aws_ssm_parameter",
      "parameter": "/prod/api/key",
      "environmentVariable": "API_KEY"
    }
  }
}
```

**Create release with tuning document**:

```bash theme={null}
tensor9 stack release create \
  -appName my-app \
  -customerName acme-corp \
  -vendorVersion "1.0.0" \
  -tuningDoc tuning.json
```

See [Docker Compose Origin Stacks](/byoc/origin-stack/docker-compose#managing-secrets) for complete documentation.

### Docker Container origin stacks

Similar to Docker Compose, define secrets in the tuning document:

**tuning.json**:

```json theme={null}
{
  "version": "V1",
  "containerResources": {
    "cpu": "2",
    "memory": "4Gi"
  },
  "secrets": {
    "db_password": {
      "source": "aws_secretsmanager",
      "secretId": "prod/db/password",
      "environmentVariable": "DB_PASSWORD"
    }
  }
}
```

The secrets are automatically injected as environment variables into your container.

See [Docker Container Origin Stacks](/byoc/origin-stack/docker#managing-secrets) for complete documentation.

### Kubernetes origin stacks

Define secrets in AWS Secrets Manager within your Terraform/CloudFormation wrapper, then reference them in Kubernetes Deployment environment variables:

```terraform theme={null}
# Define secret in AWS Secrets Manager
resource "aws_secretsmanager_secret" "db_password" {
  name = "prod/db/password"
}

# Reference in Kubernetes Deployment
resource "kubernetes_deployment" "app" {
  spec {
    template {
      spec {
        container {
          env {
            name = "DB_PASSWORD"
            value_from {
              secret_key_ref {
                name = aws_secretsmanager_secret.db_password.name
                key  = "password"
              }
            }
          }
        }
      }
    }
  }
}
```

Avoid using Kubernetes Secrets directly for sensitive data. Use AWS Secrets Manager and inject values as environment variables.

See [Kubernetes Origin Stacks](/byoc/origin-stack/kubernetes) for complete documentation.

### Application code (all origin stack types)

Regardless of origin stack type, your application code reads secrets from environment variables:

```python theme={null}
import os

# Read secrets from environment variables
db_password = os.environ['DB_PASSWORD']
api_key = os.environ['API_KEY']
```

<Note>
  Environment variables provide secret values when the application starts. Applications that need to fetch a value while running can keep using AWS Secrets Manager SDK calls such as `get_secret_value()`. For cross-cloud deployments, the [Secrets Manager service adapter](/byoc/service-adapters/aws/security-identity/secrets-manager) serves supported calls through the configured adapter endpoint. Review its target-specific limits and configure the application's access before deployment.
</Note>
