A HashiCorp Vault plugin for dynamic, secure management of OpenAI service accounts and API keys using the OpenAI Admin API. This plugin enables you to create, rotate, and revoke OpenAI project service accounts and API keys on demand, with full automation and security best practices.
This plugin was developed and tested with Vault 1.19.4.
Important
Use at your own risk and conduct your own testing before deploying. This plugin is not officially supported by HashiCorp and is provided as-is.
- Features
- Quick Start
- API Reference
- Installation
- Metrics and Monitoring
- Development
- Usage with Docker
- Usage without Docker
- Vagrant Development Environment
- License
- Dynamic Service Accounts: Create OpenAI service accounts (with API keys) with configurable TTLs for improved security.
- Automatic Cleanup: Service accounts and API keys are automatically cleaned up when leases expire.
- Admin API Key Rotation: Securely rotate OpenAI admin keys manually or on a schedule.
- Metrics and Monitoring: Prometheus-compatible metrics for credential issuance, revocation, and API errors.
- Containerized Deployment: Run as a containerized Vault plugin with Docker (Linux only).
Note: Only dynamic service account credentials are supported.
You can download the pre-built plugin binary from the latest release page.
# Extract the plugin binary (replace VERSION with the latest release version)
mkdir -p ./bin
curl -L -o ./bin/vault-plugin-secrets-openai https://github.com/gitrgoliveira/vault-plugin-secrets-openai/releases/download/VERSION/vault-plugin-secrets-openai
chmod +x ./bin/vault-plugin-secrets-openaivault server -dev -dev-plugin-dir=./bin
# In another terminal
export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=root
vault plugin register -sha256=$(shasum -a 256 ./bin/vault-plugin-secrets-openai | cut -d' ' -f1) \
secret vault-plugin-secrets-openai
vault secrets enable -path=openai vault-plugin-secrets-openaivault write openai/config \
admin_api_key="sk-admin-..." \
admin_api_key_id="admin-key-id-..." \
organization_id="org-123456"vault write openai/roles/my-role \
project_id="proj_my-project" \
service_account_name_template="vault-{{.RoleName}}-{{.RandomSuffix}}" \
ttl=1h \
max_ttl=24hvault read openai/creds/my-roleSample response:
Key Value
--- -----
lease_id openai/creds/app-role/abcdef12345
lease_duration 30m
lease_renewable false
api_key sk-...
api_key_id api_key_abc123
service_account vault-app-role-12345
service_account_id svc_abc123
POST /openai/config
PUT /openai/config
Configures the OpenAI secrets engine with admin API credentials.
Parameters:
admin_api_key(string, required) - Admin API key for OpenAIadmin_api_key_id(string, required) - Admin API key ID for OpenAIorganization_id(string, required) - Organization ID for OpenAIapi_endpoint(string, optional) - URL for the OpenAI API (default:https://api.openai.com/v1)rotation_period(duration, optional) - Period between automatic admin API key rotationsrotation_window(duration, optional) - Window during which rotation can occurdisable_automated_rotation(bool, optional) - Disable automated rotation of admin credentials
Example:
vault write openai/config \
admin_api_key="sk-admin-..." \
admin_api_key_id="admin-key-id-..." \
organization_id="org-123456" \
rotation_period=604800GET /openai/config
Returns the current configuration (sensitive fields are not returned).
Response Fields:
api_endpoint- The configured API endpointorganization_id- The organization IDadmin_api_key_id- The admin API key IDrotation_period- Automatic rotation period (if enabled)rotation_window- Rotation window (if enabled)last_rotated- Last rotation timestamp (if automated rotation is enabled)
DELETE /openai/config
Removes the configuration.
POST /openai/config/rotate
Manually rotates the admin API key. Creates a new admin API key and revokes the old one.
POST /openai/roles/{name}
PUT /openai/roles/{name}
Creates or updates a role definition for generating dynamic credentials.
Parameters:
name(string, required) - Name of the roleproject_id(string, required) - OpenAI Project ID (e.g.,proj_abc123)service_account_name_template(string, optional) - Template for service account names (default:vault-{{.RoleName}}-{{.RandomSuffix}})service_account_description(string, optional) - Description for service accounts (default:Service account created by Vault)ttl(duration, optional) - Default TTL for API keys (default:1h)max_ttl(duration, optional) - Maximum TTL for API keys (default:24h)
Example:
vault write openai/roles/analytics \
project_id="proj_abc123" \
service_account_name_template="analytics-{{.RoleName}}-{{.RandomSuffix}}" \
ttl=2h \
max_ttl=24hGET /openai/roles/{name}
Returns the configuration for a specific role.
GET /openai/roles
Lists all configured roles.
DELETE /openai/roles/{name}
Deletes a role definition.
GET /openai/creds/{role_name}
Generates new dynamic OpenAI credentials using the specified role.
Parameters:
role_name(string, required) - Name of the role to usettl(duration, optional) - Custom TTL for this credential (must not exceed role's max_ttl)
Example:
vault read openai/creds/analytics ttl=1hgit clone https://github.com/gitrgoliveira/vault-plugin-secrets-openai.git
cd vault-plugin-secrets-openai
make build- Copy the plugin binary to your Vault plugins directory:
cp ./bin/vault-plugin-secrets-openai /path/to/vault/plugins/
- Calculate the SHA256 sum of the plugin:
SHA256=$(shasum -a 256 /path/to/vault/plugins/vault-plugin-secrets-openai | cut -d' ' -f1) - Register the plugin with Vault:
vault plugin register -sha256=$SHA256 secret vault-plugin-secrets-openai - Enable the OpenAI secrets engine:
vault secrets enable -path=openai -plugin-name=vault-plugin-secrets-openai plugin
This plugin emits Prometheus-compatible metrics via Vault's telemetry system for observability and monitoring. These metrics can be scraped by Prometheus or viewed via Vault's telemetry endpoints.
- Go 1.25.4+
- Vault 1.19+ for containerized plugin support
- Vagrant (for containerized plugin usage)
Note: Building and running Vault plugins with Docker is only supported on Linux hosts. If you are on macOS or Windows, you must build the plugin binary on a Linux machine or use a Linux VM/container for plugin development and testing. See the Vault documentation for details.
You can run the Vault OpenAI Secrets Plugin in a containerized environment using Docker. This is the recommended approach for most users.
make build-releaseA sample Dockerfile is provided. Build the image:
make release VERSION=0.0.3export VAULT_ADDR=http://127.0.0.1:8200
export VAULT_TOKEN=root
export DOCKER_HOST=unix:///run/user/1000/docker.sock # Adjust if using a different Docker socket
nohup env DOCKER_HOST=$DOCKER_HOST vault server -dev -dev-root-token-id=root > vault.log 2>&1 &
# Get the Docker image SHA256
PLUGIN_SHA256=$(docker images --no-trunc --format="{{ .ID }}" vault-plugin-secrets-openai:0.0.3 | cut -d: -f2)
# Register the plugin runtime (if using containerized plugins)
vault plugin runtime register -type=container -rootless=true -oci_runtime=runsc runsc
# Register the plugin with Vault (replace 0.0.3 with your version)
vault plugin register \
-sha256="$PLUGIN_SHA256" \
-oci_image="vault-plugin-secrets-openai" \
-runtime="runsc" \
-version="0.0.3" \
secret vault-plugin-secrets-openai
# Enable the secrets engine
vault secrets enable -path=openai vault-plugin-secrets-openai# Configure with your OpenAI admin API key
vault write openai/config admin_api_key="$OPENAI_ADMIN_API_KEY" \
admin_api_key_id="$ADMIN_API_KEY_ID" \
organization_id="$OPENAI_ORG_ID" \
rotation_period="720h"
vault read openai/config
Key Value
--- -----
admin_api_key_id key_OInm3Qed3kNn4BUQ
api_endpoint https://api.openai.com/v1
disable_automated_rotation false
last_rotated 2025-07-02T15:30:45+00:00
organization_id org-gAZ0NbaPX8FD2YcdLsHiKx8v
rotation_period 720h
rotation_schedule n/a
rotation_window 0 The admin API key is used by Vault to create and manage service accounts in your OpenAI organization. The rotation period determines how often this root credential is automatically rotated. See all supported parameters here.
You can also use vault write -force openai/config/rotate to force the rotation.
Roles define the permissions and TTL for credentials generated for specific applications:
# Create a role for your application
vault write openai/roles/my-application project_id="$OPENAI_TEST_PROJECT_ID" \
service_account_name_template="vault-{{.RoleName}}-{{.RandomSuffix}}" \
ttl=”1h” max_ttl=”24h”### 7. Generate an API Key
```shell
vault read openai/creds/my-applicationSample response:
Key Value
--- -----
lease_id openai/creds/my-application/abcdef12345
lease_duration 1h
lease_renewable true
api_key sk-...
api_key_id api_key_abc123
service_account vault-my-application-12345
service_account_id svc_abc123
You can also run the plugin directly on your host system (Linux/macOS) without Docker.
make buildvault server -dev -dev-plugin-dir=./bin
# In another terminal
export VAULT_ADDR=http://127.0.0.1:8200
vault plugin register -sha256=$(shasum -a 256 ./bin/vault-plugin-secrets-openai | cut -d' ' -f1) \
secret vault-plugin-secrets-openai
vault secrets enable -path=openai -plugin-name=vault-plugin-secrets-openai pluginvault write openai/config \
admin_api_key="sk-admin-..." \
admin_api_key_id="admin-key-id-..." \
organization_id="org-123456"This project provides a robust Vagrant-based development environment for building, testing, and running the Vault OpenAI Secrets Plugin with support for rootless Docker and gVisor/runsc.
- Automated provisioning of Go, Docker (rootless), and gVisor/runsc for containerized plugin testing.
- Rootless Docker setup for the
vagrantuser, with correct socket and runtime configuration. - gVisor/runsc installed from the official APT repository, with fallback to
runcif runsc is not compatible with rootless mode. - Automated plugin build, Docker image creation, and Vault plugin registration inside the VM.
- Integration and unit test scripts for plugin validation.
-
Start the Vagrant VM and provision:
vagrant up
This will:
- Install Go, Docker (rootless), and gVisor/runsc
- Set up Docker for the
vagrantuser in rootless mode - Build the plugin and Docker image
- Start Vault in dev mode and register the plugin
-
SSH into the VM:
vagrant ssh cd vault-plugin-secrets-openai -
Run tests:
- Unit tests:
./scripts/run_tests.sh
- Integration tests:
You will be prompted for your OpenAI Admin API Key, Organization ID, and Test Project ID.
./scripts/run_tests.sh --integration
- Unit tests:
- The provisioning scripts attempt to use
runscas the Docker runtime for containerized plugin testing. - gVisor/runsc is not fully compatible with rootless Docker due to systemd/cgroup limitations. If runsc fails, the scripts will automatically fall back to the default
runcruntime for plugin build and Vault registration. - The correct Docker socket (
/run/user/1000/docker.sock) is set via theDOCKER_HOSTenvironment variable for all Vault and Docker operations.
VAULT_ADDR,VAULT_TOKEN, andDOCKER_HOSTare set automatically in the VM for thevagrantuser.- For integration tests, you will need to provide:
OPENAI_ADMIN_API_KEYOPENAI_ORG_IDOPENAI_TEST_PROJECT_ID
- If you see errors about Docker socket permissions or plugin registration, ensure that
DOCKER_HOSTis set to the rootless Docker socket and that Vault is running with this environment variable. - If you need to reprovision from scratch:
vagrant destroy -f vagrant up
scripts/vagrant_provision_as_root.sh: Installs system dependencies (Go, Docker, gVisor, etc.)scripts/vagrant_provision_as_user.sh: Configures Docker rootless mode, builds the plugin, starts Vault, and registers the plugin.scripts/run_tests.sh: Runs unit and integration tests for the plugin.
This project is licensed under the Mozilla Public License 2.0 - see the LICENSE file for details.