PHPackages                             pantheon-systems/terminus-secrets-manager-plugin - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. pantheon-systems/terminus-secrets-manager-plugin

ActiveTerminus-plugin

pantheon-systems/terminus-secrets-manager-plugin
================================================

Secrets handling plugin for Terminus

1.3.4(10mo ago)9144.5k↑94.7%8[10 PRs](https://github.com/pantheon-systems/terminus-secrets-manager-plugin/pulls)MITPHPCI passing

Since Sep 14Pushed 2mo ago6 watchersCompare

[ Source](https://github.com/pantheon-systems/terminus-secrets-manager-plugin)[ Packagist](https://packagist.org/packages/pantheon-systems/terminus-secrets-manager-plugin)[ RSS](/packages/pantheon-systems-terminus-secrets-manager-plugin/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (3)Versions (30)Used By (0)

Terminus Secrets Manager Plugin
===============================

[](#terminus-secrets-manager-plugin)

Pantheon’s Secrets Manager Terminus plugin is key to maintaining industry best practices for secure builds and application implementation. Secrets Manager provides a convenient mechanism for you to manage your secrets and API keys directly on the Pantheon platform.

Table of Contents
-----------------

[](#table-of-contents)

- [Overview](#overview)
    - [Key Features](#key-features)
    - [Early Access](#early-access)
- [Concepts](#concepts)
    - [Secret](#secret)
    - [Secret type](#secret-type)
    - [Secret scope](#secret-scope)
    - [Owning entity](#owning-entity)
    - [Site-owned secrets](#site-owned-secrets)
    - [Organization-owned secrets](#organization-owned-secrets)
    - [Environment override](#environment-override)
- [The life of a secret](#the-life-of-a-secret)
- [Plugin Usage](#plugin-usage)
    - [Secrets Manager Plugin Requirements](#secrets-manager-plugin-requirements)
    - [Installation](#installation)
    - [Site secrets Commands](#site-secrets-commands)
    - [Organization secrets Commands](#organization-secrets-commands)
    - [Help](#help)
- [Rate Limiting](#rate-limiting)
- [Use Secrets with Integrated Composer](#use-secrets-with-integrated-composer)
    - [Mechanism 1: Oauth Composer authentication](#mechanism-1-oauth-composer-authentication)
    - [Mechanism 2: HTTP Basic Authentication](#mechanism-2-http-basic-authentication)
- [Using Secrets in Your Site Code](#using-secrets-in-your-site-code)
    - [Using pantheon\_get\_secret()](#using-pantheon_get_secret)
    - [Using the Customer Secrets PHP SDK](#using-the-customer-secrets-php-sdk)
- [Use Secrets in Drupal through the Key module](#use-secrets-in-drupal-through-the-key-module)

Overview
--------

[](#overview)

### Key Features

[](#key-features)

- Securely host and maintain secrets on Pantheon
- Create and update secrets via Terminus
- Use private repositories in Integrated Composer builds
- Ability to set a `COMPOSER_AUTH` environment variable and/or a Composer `auth.json` authentication file with Terminus commands
- Ability to define site and org ownership of secrets
- Propagate organization-owned secrets to all the sites in the org
- Ability to define the degree of secrecy for each managed item
- Secrets are encrypted at rest

### Early Access

[](#early-access)

The Secrets Manager plugin is available in Early Access. Visit the [Pantheon Slack channel](https://slackin.pantheon.io/) (or sign up for the channel if you don't already have an account) to learn more. Please review [Pantheon's Software Evaluation Licensing Terms](https://legal.pantheon.io/#contract-hkqlbwpxo) for more information about access to our software.

Concepts
--------

[](#concepts)

### Secret

[](#secret)

A key-value pair that should not be exposed to the general public, typically something like a password, API key, or the contents of a peer-to-peer cryptographic certificate. SSL certificates that your site uses to serve pages are out of scope of this process and are managed by the dashboard in a different place. See the documentation for SSL certificates for details.

### Secret type

[](#secret-type)

This is a field on the secret record. It defines the usage for this secret and how it is consumed. Current types are:

- `runtime`: this secret will be used to retrieve it in application runtime using the `pantheon_get_secret()` function or the Customer Secrets PHP SDK. This is the recommended way to set information like API keys for third-party integrations in your application.
- `env`: this secret will be used to set environment variables in the application runtime. This type is not yet in use in Early Access.
- `composer`: this secret type is used for composer authentication to private packages.
- `file`: this type allows you to store files in the secrets. This type is not yet in use in Early Access.

Note that you can only set one type per secret and this cannot be changed later (unless you delete and recreate the secret).

### Secret scope

[](#secret-scope)

This is a field on the secret record. It defines the components that have access to the secret value. Current scopes are:

- `ic`: this secret will be readable by the Integrated Composer runtime. You should use this scope to get access to your private repositories.
- `web`: this secret will be readable by the application runtime.
- `user`: this secret will be readable by the user. This scope should be set if you need to retrieve the secret value at a later stage.

Note that you can set multiple scopes per secret, but scopes cannot be changed later (unless you delete and recreate the secret).

### Owning entity

[](#owning-entity)

Secrets are currently either owned by a site or an organization. Within that owning entity, the secret may have zero or more environment overrides.

### Site-owned secrets

[](#site-owned-secrets)

This is a secret set for a specific site using the site ID. Based on the type and scope, this secret will be loaded on the different scenarios that will be supported by Secrets in Pantheon.

### Organization-owned secrets

[](#organization-owned-secrets)

This is a secret set not for a given site but for an organization. This secret will be inherited by ALL sites OWNED by this organization.

**Note**: Secrets owned by [Supporting Organizations](https://docs.pantheon.io/agency-tips#become-a-supporting-organization) won't apply to sites they support. Only the Owner organization's secrets will apply.

### Environment override

[](#environment-override)

In some cases it will be necessary to have different values for the secret when that secret is accessed in different Pantheon environments. You may set an environment override value for any existing secret value.

**Note**: If the secret does not exist, there is no secret environment to override, and you will get an error.

 ```
classDiagram
OrganizationSecretAPIPassword --> SiteSecretAPIPassword
SiteSecretAPIPassword  --> IntegratedComposerAPIPassword : no overrides
OrganizationSecretAPIPassword : string name apipassword
OrganizationSecretAPIPassword : string value ball00n
SiteSecretAPIPassword : Inherits value from Org
SiteSecretAPIPassword : No Overrides
IntegratedComposerAPIPassword: value ball00n

OrganizationSecretOverrideExample --> SiteSecretOverrideExample
SiteSecretOverrideExample --> SiteSecretOverrideExampleDev : default value
SiteSecretOverrideExample --> SiteSecretOverrideExampleTest : env override value
SiteSecretOverrideExample --> SiteSecretOverrideExampleLive : env override value
OrganizationSecretOverrideExample : string name apipassword
OrganizationSecretOverrideExample : string value ball00n
SiteSecretOverrideExample : Inherits value from Org
SiteSecretOverrideExample : No Site Overrides
SiteSecretOverrideExampleDev: value ball00n
SiteSecretOverrideExampleDev: defaultValue()
SiteSecretOverrideExampleTest: value ball00n2
SiteSecretOverrideExampleTest: overridden()
SiteSecretOverrideExampleLive: value ball00n3
SiteSecretOverrideExampleLive: overridden()
```

      Loading The life of a secret
--------------------

[](#the-life-of-a-secret)

When a given runtime (e.g. Integrated Composer or an environment php runtime) fetches secrets for a given site (and env), the process will be as follows:

- Fetch secrets for site (of the given type and scopes).
- Apply environment overrides (if any) based on the requesting site environment.
- If the site is owned by an organization:

    - Fetch the organization secrets.
    - Apply environment overrides (if any) based on the requesting site environment.
    - Merge the organization secrets with the site secrets (the following example will describe this process in more detail).

Let's go through this with an example: assume you have a site named `my-site` which belongs to an organization `my-org`. You also have another site `my-other-site` which belongs to your personal Pantheon account.

When Integrated Composer attempts to get secrets for `my-other-site` it will go like this:

- Get the secrets of scope `ic` for `my-other-site`.
- Apply environment overrides for the current environment (see **Note** below).
- Look at `my-other-site` owner. In this case, it is NOT an organization so there are no organization secrets to merge.
- Process the resulting secrets to make them available to Composer.

On the other hand, when Integrated Composer attempts to get secrets for `my-site`, it will go like this:

- Get the secrets of scope `ic` for `my-site`.
- Apply environment overrides for the current environment (see **Note** below).
- Look at the site owner. It determines it is the organization `my-org`.
- Get the secrets for the organization `my-org` with scope `ic`.
- Apply the environment overrides to those secrets for the current environment (see **Note** below).
- Merge the resulting organization secrets with the site secrets with the following caveats:
    - Site secrets take precedence over organization secrets. This means that the value for site-owned secret named `foo` will be used instead of the value for an org-owned secret with the same name `foo`.
    - Only the secrets for the OWNER organization are being merged. If the site has a Supporting Organization, it will be ignored.
- Process the resulting secrets to make them available to Composer.

**Note:** Due to platform design, the "environment" for Integrated Composer will always be either `dev` or a multidev. It will never be `test` or `live`. Therefore we do not recommend using environment overrides for Composer access. The primary use-case for environment overrides is for the CMS key-values and environment variables that need to be different between your live and non-live environments.

Plugin Usage
------------

[](#plugin-usage)

### Secrets Manager Plugin Requirements

[](#secrets-manager-plugin-requirements)

Secrets Manager requires the following:

- A Pantheon account
- A site that uses [Integrated Composer](https://docs.pantheon.io/guides/integrated-composer) and runs PHP &gt;= 8.0
- Terminus 3.0+

### Installation

[](#installation)

Terminus 3.x has built in plugin management.

Run the command below to install Terminus Secrets Manager.

```
terminus self:plugin:install terminus-secrets-manager-plugin

```

### Site secrets Commands

[](#site-secrets-commands)

#### Set a secret

[](#set-a-secret)

The secrets `set` command takes the following format:

- `Name`
- `Value`
- `Type`
- `One or more scopes`

**Run the command below to set a new secret in Terminus:**

```
terminus secret:site:set

[notice] Success

```

```
terminus secret:site:set  file.json "{}" --type=file

[notice] Success

```

```
terminus secret:site:set   --scope=user,ic

[notice] Success

```

Note: If you do not include a `type` or `scope` flag, these values will be set to the defaults (`runtime` and `user` respectively).

**Run the command below to update an existing secret in Terminus:**

```
terminus secret:site:set

[notice] Success

```

Note: When updating an existing secret, `type` and `scope` should NOT be passed as they are immutable. You should delete and recreate the secret if you need to update those properties.

**Add or update an environment override for an existing secret in Terminus:**

```
terminus secret:site:set .

[notice] Success

```

Note: You can add an environment override only to existing secrets; otherwise, it will fail.

#### List secrets

[](#list-secrets)

The secrets `list` command provides a list of all secrets available for a site. The following fields are available:

- `Secret name`
- `Secret scopes`
- `Secret type`
- `Secret value`
- `Environment override values`
- `Org values`

Note that the `value` field will contain a placeholder value unless the `user` scope was specified when the secret was set.

**Run the command below to list a site’s secrets:**

```
terminus secret:site:list

 ------------- ------------- ---------------------------
  Secret name   Secret type   Secret value
 ------------- ------------- ---------------------------
  secret-name   env           secrets-content
 ------------- ------------- ---------------------------

```

```
terminus secret:site:list  --fields="*"

 ---------------- ------------- ------------------------------------------ --------------- ----------------------------- --------------------
  Secret name      Secret type   Secret value                               Secret scopes   Environment override values   Org values
 ---------------- ------------- ------------------------------------------ --------------- ----------------------------- --------------------
  foo              env           ***                                        web, user
  foo2             runtime       bar2                                       web, user                                     default=barorg
  foo3             env           dummykey                                   web, user       live=sendgrid-live
 ---------------- ------------- ------------------------------------------ --------------- ----------------------------- --------------------

```

#### Delete a secret

[](#delete-a-secret)

The secrets `delete` command will remove a secret and all of its overrides.

**Run the command below to delete a secret:**

```
terminus secret:site:delete

[notice] Success

```

**Run the command below to delete an environment override for a secret:**

```
terminus secret:site:delete .

[notice] Success

```

#### Generate file for local development

[](#generate-file-for-local-development)

The secrets `local-generate` command will generate a json file useful for local development emulation of secrets.

**Run the command below to get a json file:**

```
terminus secret:site:local-generate  --filepath=./secrets.json
[notice] Secrets file written to: ./secrets.json. Please review this file and adjust accordingly for your local usage.

```

### Organization secrets Commands

[](#organization-secrets-commands)

#### Set a secret

[](#set-a-secret-1)

The secrets `set` command takes the following format:

- `Name`
- `Value`
- `Type`
- `One or more scopes`

**Run the command below to set a new secret in Terminus:**

```
terminus secret:org:set

[notice] Success

```

```
terminus secret:org:set  file.json "{}" --type=file

[notice] Success

```

```
terminus secret:org:set   --scope=user,ic

[notice] Success

```

Note: If you do not include a `type` or `scope` flag, their defaults will be `runtime` and `user` respectively.

**Run the command below to update an existing secret in Terminus:**

```
terminus secret:org:set

[notice] Success

```

Note: When updating an existing secret, `type` and `scope` should NOT be passed as they are immutable. You should delete and recreate the secret if you need to update those properties.

**Add or update an environment override for an existing secret in Terminus:**

```
terminus secret:org:set --env=

[notice] Success

```

Note: You can add an environment override only to existing secrets; otherwise, it will fail.

#### List secrets

[](#list-secrets-1)

The secrets `list` command provides a list of all secrets available for an organization. The following fields are available:

- `Secret name`
- `Secret scopes`
- `Secret type`
- `Secret value`
- `Environment override values`

Note that the `value` field will contain a placeholder value unless the `user` scope was specified when the secret was set.

**Run the command below to list a site’s secrets:**

```
terminus secret:org:list

 ------------- ------------- ---------------------------
  Secret name   Secret type   Secret value
 ------------- ------------- ---------------------------
  secret-name   env           secrets-content
 ------------- ------------- ---------------------------

```

```
terminus secret:org:list  --fields="*"

 ---------------- ------------- ------------------------------------------ --------------- -----------------------------
  Secret name      Secret type   Secret value                               Secret scopes   Environment override values
 ---------------- ------------- ------------------------------------------ --------------- -----------------------------
  foo              env           bar                                        web, user
  foo2             runtime       bar2                                       web, user
  foo3             env           dummykey                                   web, user       live=sendgrid-live
 ---------------- ------------- ------------------------------------------ --------------- -----------------------------

```

#### Delete a secret

[](#delete-a-secret-1)

The secrets `delete` command will remove a secret and all of its overrides.

**Run the command below to delete a secret:**

```
terminus secret:org:delete

[notice] Success

```

**Run the command below to delete an environment override for a secret:**

```
terminus secret:org:delete --env=

[notice] Success

```

### Help

[](#help)

Run `terminus list secret` for a complete list of available commands. Use terminus help to get help with a specific command.

Rate Limiting
-------------

[](#rate-limiting)

The service supports up to 3 requests per second per user through Terminus. If you hit that limit, the API will return a `429` error code and the plugin will throw an error.

The PHP SDK and `pantheon_get_secret()` function are not affected by this rate limiting.

Use Secrets with Integrated Composer
------------------------------------

[](#use-secrets-with-integrated-composer)

You must configure your private repository and provide an authentication token before you can use the Secrets Manager Terminus plugin with Integrated Composer. You could use either of the following mechanisms to setup this authentication.

### Mechanism 1: Oauth Composer authentication

[](#mechanism-1-oauth-composer-authentication)

#### GitHub Repository

[](#github-repository)

1. [Generate a Github token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). The Github token must have all "repo" permissions selected.

    NOTE: Check the repo box that selects all child boxes. **Do not** check all child boxes individually as this does not set the correct permissions.

    [![image](https://user-images.githubusercontent.com/87093053/191616923-67732035-08aa-41c3-9a69-4d954ca02560.png)](https://user-images.githubusercontent.com/87093053/191616923-67732035-08aa-41c3-9a69-4d954ca02560.png)
2. Set the secret value to the token via terminus: `terminus secret:site:set  github-oauth.github.com  --type=composer --scope=user,ic`
3. Add your private repository to the `repositories` section of `composer.json`:

    ```
    {
        "type": "vcs",
        "url": "https://github.com/your-organization/your-repository-name"
    }
    ```

    Your repository should contain a `composer.json` that declares a package name in its `name` field. If it is a WordPress plugin or a Drupal module, it should specify a `type` of `wordpress-plugin` or `drupal-module` respectively. For these instructions, we will assume your package name is `your-organization/your-package-name`.
4. Require the package defined by your private repository's `composer.json` by either adding a new record to the `require` section of the site's `composer.json` or with a `composer require` command:

    ```
    composer require your-organization/your-package-name
    ```
5. Commit your changes and push to Pantheon.

#### GitLab Repository

[](#gitlab-repository)

1. [Generate a GitLab token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html). Ensure that `read_repository` scope is selected for the token.
2. Set the secret value to the token via Terminus: `terminus secret:site:set  gitlab-oauth.gitlab.com  --type=composer --scope=user,ic`
3. Add your private repository to the `repositories` section of `composer.json`:

    ```
    {
        "type": "vcs",
        "url": "https://gitlab.com/your-group/your-repository-name"
    }
    ```

    Your repository should contain a `composer.json` that declares a package name in its `name` field. If it is a WordPress plugin or a Drupal module, it should specify a `type` of `wordpress-plugin` or `drupal-module` respectively. For these instructions, we will assume your package name is `your-organization/your-package-name`.
4. Require the package defined by your private repository's `composer.json` by either adding a new record to the `require` section of the site's `composer.json` or with a `composer require` command:

    ```
    composer require your-group/your-package-name
    ```
5. Commit your changes and push to Pantheon.

#### Bitbucket Repository

[](#bitbucket-repository)

1. [Generate a Bitbucket oauth consumer](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/). Ensure that Read repositories permission is selected for the consumer. Also, set the consumer as private and put a (dummy) callback URL.
2. Set the secret value to the consumer info via Terminus: `terminus secret:site:set  bitbucket-oauth.bitbucket.org " " --type=composer --scope=user,ic`
3. Add your private repository to the `repositories` section of `composer.json`:

    ```
    {
        "type": "vcs",
        "url": "https://bitbucket.org/your-organization/your-repository-name"
    }
    ```

    Your repository should contain a `composer.json` that declares a package name in its `name` field. If it is a WordPress plugin or a Drupal module, it should specify a `type` of `wordpress-plugin` or `drupal-module` respectively. For these instructions, we will assume your package name is `your-organization/your-package-name`.
4. Require the package defined by your private repository's `composer.json` by either adding a new record to the `require` section of the site's `composer.json` or with a `composer require` command:

    ```
    composer require your-organization/your-package-name
    ```
5. Commit your changes and push to Pantheon.

### Mechanism 2: HTTP Basic Authentication

[](#mechanism-2-http-basic-authentication)

You may create a `COMPOSER_AUTH json` and make it available via the `COMPOSER_AUTH` environment variable if you have multiple private repositories on multiple private domains.

Composer has the ability to read private repository access information from the environment variable: `COMPOSER_AUTH`. The `COMPOSER_AUTH` variables must be in a [specific JSON format](https://getcomposer.org/doc/articles/authentication-for-private-packages.md#http-basic).

Format example:

```
#!/bin/bash

read -e COMPOSER_AUTH_JSON getClient();
$secret = $client->getSecret('my-api-key');
$secret_value = $secret->getValue();

// Or get all secrets at once
$secrets = $client->getSecrets();
```

**Local development:** The SDK includes a fake client implementation for local development. Generate a local secrets file with:

```
terminus secret:site:local-generate  --filepath=./secrets.json
```

Then configure your local environment to use it. See the [SDK documentation](https://github.com/pantheon-systems/customer-secrets-php-sdk) for detailed local setup instructions, including examples for Lando and other development environments.

**Note:** Secrets are cached for up to 15 minutes. If you modify a secret, allow up to 15 minutes for the change to take effect in your application.

Use Secrets in Drupal through the Key module
--------------------------------------------

[](#use-secrets-in-drupal-through-the-key-module)

If you want to use Pantheon Secrets in your Drupal application through the [Key module](https://www.drupal.org/project/key), you should use the [Pantheon Secrets](https://www.drupal.org/project/pantheon_secrets) module.

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance71

Regular maintenance activity

Popularity41

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 55.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~64 days

Recently: every ~16 days

Total

17

Last Release

307d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5a89f5f15357797cbd6ec7833a28626478ae3c0ceb5fa1faa8a26d0960584c65?d=identicon)[pantheon-systems](/maintainers/pantheon-systems)

![](https://www.gravatar.com/avatar/c4f54a034246be4669b54689da9a6a57c4fef369c6ef953b01772c798f75e7f6?d=identicon)[kporras07](/maintainers/kporras07)

---

Top Contributors

[![kporras07](https://avatars.githubusercontent.com/u/2217820?v=4)](https://github.com/kporras07 "kporras07 (97 commits)")[![stovak](https://avatars.githubusercontent.com/u/119924?v=4)](https://github.com/stovak "stovak (34 commits)")[![greg-1-anderson](https://avatars.githubusercontent.com/u/612191?v=4)](https://github.com/greg-1-anderson "greg-1-anderson (22 commits)")[![scottbuscemi](https://avatars.githubusercontent.com/u/4336848?v=4)](https://github.com/scottbuscemi "scottbuscemi (8 commits)")[![namespacebrian](https://avatars.githubusercontent.com/u/87093053?v=4)](https://github.com/namespacebrian "namespacebrian (7 commits)")[![whitneymeredith](https://avatars.githubusercontent.com/u/97134315?v=4)](https://github.com/whitneymeredith "whitneymeredith (6 commits)")[![rwagner00](https://avatars.githubusercontent.com/u/1789035?v=4)](https://github.com/rwagner00 "rwagner00 (1 commits)")[![jsulz](https://avatars.githubusercontent.com/u/2693879?v=4)](https://github.com/jsulz "jsulz (1 commits)")

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/pantheon-systems-terminus-secrets-manager-plugin/health.svg)

```
[![Health](https://phpackages.com/badges/pantheon-systems-terminus-secrets-manager-plugin/health.svg)](https://phpackages.com/packages/pantheon-systems-terminus-secrets-manager-plugin)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
