Managing Secrets
When tasks or container image builds require sensitive credentials—such as API tokens, database passwords, or private registry pull keys—storing them in plaintext inside source code or configuration files exposes them to security risks. In flyte-sdk, secret management is handled through flyte.remote.Secret, which communicates with the backend SecretService to securely create, inspect, list, and delete secrets scoped to your organization, project, and domain.
Managing Secrets with the Python SDK
To create and manage secrets on your cluster, initialize the Flyte remote client and use the flyte.remote.Secret class methods.
import flyte
from flyte.remote import Secret
# Initialize the Flyte client with cluster credentials
flyte.init(
endpoint="dns:///localhost:8080",
insecure=True,
project="flytesnacks",
domain="development",
)
# 1. Create a generic secret
Secret.create(name="openai-api-key", value="sk-example-token-12345")
# 2. Create a private container registry image pull secret
Secret.create(
name="docker-hub-credentials",
value=b'{"auths":{"https://index.docker.io/v1/":{"auth":"ZXhhbXBsZTpwYXNzd29yZA=="}}}',
type="image_pull",
)
# 3. Retrieve secret metadata
secret_info = Secret.get("openai-api-key")
print(f"Secret name: {secret_info.name}, Type: {secret_info.type}")
# 4. List all secrets in the current project/domain
for s in Secret.listall():
print(f"Found secret: {s.name} ({s.type})")
# 5. Delete a secret
Secret.delete("openai-api-key")
Key Components
flyte.remote.Secret.create(name, value, type="regular"): Creates a secret on the remote control plane.valueaccepts eitherstr(stored instring_valueofSecretSpec) orbytes(stored inbinary_value). Thetypeargument accepts"regular"(which maps to protobufSecretType.SECRET_TYPE_GENERIC) or"image_pull"(which maps toSecretType.SECRET_TYPE_IMAGE_PULL_SECRET).flyte.remote.Secret.get(name): Fetches metadata for an existing secret, returning aSecretwrapper containing protobuf metadata such as creation time, overall status, and cluster presence status.flyte.remote.Secret.listall(limit=100): Fetches all secrets registered under the active organization, project, and domain. Handles gRPC pagination continuation tokens automatically.flyte.remote.Secret.delete(name): Sends aDeleteSecretRequestfor the specified secret name within the configured project and domain.
Variations & Common Scenarios
Creating Image Pull Secrets from Binary Data or Files
Image pull secrets authenticate Kubernetes clusters with private container registries (e.g., Docker Hub, GitHub Container Registry, AWS ECR). Pass a binary .dockerconfigjson string or bytes directly:
from pathlib import Path
from flyte.remote import Secret
docker_config = Path("~/.docker/config.json").expanduser().read_bytes()
Secret.create(
name="ghcr-pull-secret",
value=docker_config,
type="image_pull",
)
Asynchronous Remote Operations
All classmethods on flyte.remote.Secret are wrapped with @syncify. In asynchronous applications or services, access the underlying async coroutines and async iterators using the .aio property:
import asyncio
from flyte.remote import Secret
async def manage_secrets_async():
# Asynchronous secret creation
await Secret.create.aio(name="async-api-key", value="secret-val")
# Asynchronous secret retrieval
secret_obj = await Secret.get.aio("async-api-key")
print("Fetched:", secret_obj.name)
# Asynchronous pagination with async for
async for s in Secret.listall.aio(limit=50):
print("Secret:", s.name, s.type)
# Asynchronous deletion
await Secret.delete.aio("async-api-key")
asyncio.run(manage_secrets_async())
Inspecting Secret Metadata and Cluster Distribution
For security, Secret.get() and Secret.listall() do not expose the raw secret value. Instead, they return a Secret dataclass wrapping definition_pb2.Secret, which provides metadata and multi-cluster synchronization status:
from flyte.remote import Secret
secret = Secret.get("my-db-password")
# Access basic properties
print("Name:", secret.name)
print("Type:", secret.type) # "regular" or "image_pull"
# Access underlying protobuf metadata
meta = secret.pb2.secret_metadata
print("Created:", meta.created_time.ToDatetime().isoformat())
print("Overall Status:", meta.secret_status.overall_status)
# Check cluster presence status across connected Kubernetes clusters
for cluster_status in meta.secret_status.cluster_status:
print(f"Cluster: {cluster_status.cluster.name}, Status: {cluster_status.presence_status}")
# Convert to JSON-compatible dictionary via ToJSONMixin
secret_dict = secret.to_dict()
Managing Secrets via the CLI
The flyte command-line tool provides commands mapped directly to flyte.remote.Secret:
Create Secrets
Prompt interactively for secret value:
flyte create secret openai-api-key
Pass a string value directly:
flyte create secret openai-api-key --value "sk-example-token-12345"
Create a secret from a file (e.g., a private key or Docker config):
flyte create secret ghcr-secret --from-file ~/.docker/config.json --type image_pull
Get and List Secrets
List all secrets in the current project and domain:
flyte get secret
Get metadata for a specific secret in JSON format:
flyte get secret openai-api-key
Delete Secrets
flyte delete secret openai-api-key
Consuming Secrets in Tasks and Images
Once created on the remote control plane, secrets are referenced in task definitions and container image build contexts using flyte.Secret from flyte._secret:
In Tasks
Inject secrets as environment variables into task executions:
import os
import flyte
from flyte import Secret, task
# If as_env_var is omitted, the env var name defaults to uppercase with dashes replaced by underscores (e.g. OPENAI_API_KEY)
@task(secrets=Secret("openai-api-key", as_env_var="OPENAI_API_KEY"))
def call_api() -> str:
token = os.environ["OPENAI_API_KEY"]
return f"Authenticated with token prefix {token[:4]}"
In Image Builds
Mount secrets during image builds (e.g., to download packages from private package registries):
from flyte import Image, Secret
image = (
Image.from_debian_base()
.with_pip_packages(
"private-pkg",
secret_mounts=[Secret(key="GITHUB_PAT", as_env_var="GITHUB_TOKEN")],
)
.with_apt_packages(
"git",
secret_mounts=[Secret(key="apt-secret", mount="/etc/apt/apt-secret")],
)
)
Troubleshooting
RuntimeError: Client not initialized
- Cause: Invoking
Secret.create(),Secret.get(),Secret.listall(), orSecret.delete()before initializing the SDK client. - Fix: Call
flyte.init(...)with your target cluster endpoint, project, and domain, or pass--projectand--domainflags when using the CLI.
Secret Not Found Across Project / Domain
- Cause:
flyte.remote.Secretscopes all requests (CreateSecretRequest,GetSecretRequest,ListSecretsRequest,DeleteSecretRequest) toorganization,project, anddomaindefined inget_common_config(). - Fix: Verify that the active project and domain in
flyte.init()match where the secret was originally created.
TypeError: object NoneType can't be used in 'await' expression
- Cause: Using
await Secret.get(...)instead ofawait Secret.get.aio(...). - Fix: Methods decorated with
@syncifyrun synchronously when called directly. When writing async code, always use the.aioattribute:await Secret.get.aio(name).
Secret Values Missing in get() or listall() Output
- Behavior: The backend
SecretServicestrips secret payload values fromGetSecretResponseandListSecretsResponseto prevent credentials leakage. - Fix: Secrets can only be written during
Secret.create(). Values are delivered directly to tasks and build containers at execution time by the Flyte engine.