USMAN’S INSIGHTS
AI ARCHITECT
  • Home
  • About
  • Thought Leadership
  • Book
Press / Contact
USMAN’S INSIGHTS
AI ARCHITECT
⌘F
HomeBook
HomeBookYour API Keys Are Sitting Inside Your Docker Image Right Now
Previous Chapter
Jobs API Scheduled Tasks
Next Chapter
Capstone Dapr-Enabled Task API
AI NOTICE: This is the table of contents for the SPECIFIC CHAPTER only. It is NOT the global sidebar. For all chapters, look at the main navigation.

On this page

31 sections

Progress0%
1 / 31

Muhammad Usman Akbar Entity Profile

Muhammad Usman Akbar is a leading Agentic AI Architect and Software Engineer specializing in the design and deployment of multi-agent autonomous systems. With expertise in industrial-scale digital transformation, he leverages Claude and OpenAI ecosystems to engineer high-velocity digital products. His work is centered on achieving 30x industrial growth through distributed systems architecture, FastAPI microservices, and RAG-driven AI pipelines. Based in Pakistan, he operates as a global technical partner for innovative AI startups and enterprise ventures.

USMAN’S INSIGHTS
AI ARCHITECT

Transforming businesses into autonomous AI ecosystems. Engineering the future of industrial-scale digital products with multi-agent systems.

30X Growth
AI-First
Innovation

Navigation

  • Home
  • Book
  • About
  • Contact
Let's Collaborate

Have a Project in Mind?

Let's build something extraordinary together. Transform your vision into autonomous AI reality.

Start Your Transformation

© 2026 Muhammad Usman Akbar. All rights reserved.

Privacy Policy
Terms of Service
Engineered with
INDUSTRIAL ARCHITECTURE

Secrets and Configuration

Module 7 takes the agent you built in Module 6 and turns it into a production cloud service. You'll containerize the stack, orchestrate it on Kubernetes, automate delivery, and operate it with observability, security, and cost controls. The goal: a reliable Digital FTE that runs 24/7 for real users.

Prerequisites: Modules 4-6. You need a working agent service to deploy.

Your Task API needs an API key to call an external service. You hardcode it in your Docker image. Then you realize everyone who pulls your image can extract that key. You move it to an environment variable. Better, but now your deployment YAML has the key in plain text. Anyone with cluster access can read your manifests.

This isn't a hypothetical concern. In production systems, credential leaks cause real damage. API keys get revoked, databases get accessed by unauthorized parties, and teams spend days rotating compromised secrets across dozens of services.

Dapr's secrets building block solves this by providing a unified API to access secrets from multiple stores---Kubernetes secrets, HashiCorp Vault, Azure Key Vault, AWS Secrets Manager---without your application knowing which store is being used. This lesson shows you how to retrieve secrets securely in your Python code and reference them in component configurations.


Creating Kubernetes Secrets

Before Dapr can retrieve secrets, they must exist in Kubernetes. The kubectl create secret command creates secrets from literal values or files.

Create a Secret for API Credentials

bash
kubectl create secret generic api-credentials \ --from-literal=api-key=my-secret-key-123 \ --from-literal=api-secret=my-secret-value-456

Output:

text
secret/api-credentials created

Verify the Secret Exists

bash
kubectl get secret api-credentials -o yaml

Output:

yaml
apiVersion: v1 kind: Secret metadata: name: api-credentials namespace: default type: Opaque data: api-key: bXktc2VjcmV0LWtleS0xMjM= api-secret: bXktc2VjcmV0LXZhbHVlLTQ1Ng==

Notice the values are base64-encoded (not encrypted). Kubernetes secrets provide access control, not encryption at rest by default.

Create a Redis Password Secret

For later use with component YAML:

bash
kubectl create secret generic redis-password \ --from-literal=password=redis-secret-pass

Output:

text
secret/redis-password created

The Kubernetes Secrets Store Component

Dapr needs a secrets store component to know where to retrieve secrets from. The Kubernetes secrets store is built-in---no extra installation required.

Component YAML

yaml
# components/kubernetes-secrets.yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: kubernetes-secrets namespace: default spec: type: secretstores.kubernetes version: v1 metadata: []

This component:

  • type: secretstores.kubernetes tells Dapr to use the Kubernetes Secrets API
  • metadata: Empty because Dapr runs inside Kubernetes and has native access
  • name: Your code references this name when calling get_secret()

Deploy the Component

bash
kubectl apply -f components/kubernetes-secrets.yaml

Output:

text
component.dapr.io/kubernetes-secrets created

Verify Component Registration

bash
kubectl get components

Output:

text
NAME AGE kubernetes-secrets 5s statestore 1h pubsub 1h

Retrieving Secrets with DaprClient

The Secrets API endpoint is /v1.0/secrets/{store}/{key}. With the Python SDK, you use DaprClient.get_secret().

Synchronous Pattern

python
from dapr.clients import DaprClient with DaprClient() as client: secret = client.get_secret( store_name='kubernetes-secrets', key='api-credentials' ) api_key = secret.secret.get('api-key') print(f"Got API key: {api_key[:4]}...")

Output:

text
Got API key: my-s...

Async Pattern with Context Manager

For FastAPI applications, use the async pattern:

python
from dapr.clients.aio import DaprClient from fastapi import FastAPI app = FastAPI() @app.get("/config") async def get_config(): async with DaprClient() as client: secret = await client.get_secret( store_name='kubernetes-secrets', key='api-credentials' ) api_key = secret.secret.get('api-key') return {"api_key_prefix": api_key[:4] + "..."}

Output:

text
{"api_key_prefix": "my-s..."}

Getting Specific Keys from a Secret

Kubernetes secrets can contain multiple key-value pairs. The get_secret() response includes all keys:

python
async with DaprClient() as client: secret = await client.get_secret( store_name='kubernetes-secrets', key='api-credentials' ) # Access individual keys api_key = secret.secret.get('api-key') api_secret = secret.secret.get('api-secret') print(f"Key: {api_key}") print(f"Secret: {api_secret}")

Output:

text
Key: my-secret-key-123 Secret: my-secret-value-456

Getting Bulk Secrets

To retrieve all secrets from a store:

python
async with DaprClient() as client: secrets = await client.get_bulk_secret( store_name='kubernetes-secrets' ) for secret_name, values in secrets.secrets.items(): print(f"{secret_name}: {list(values.keys())}")

Output:

text
api-credentials: ['api-key', 'api-secret'] redis-password: ['password']

Referencing Secrets in Component YAML

Hard-coding credentials in component YAML defeats the purpose of secrets. Dapr supports secretKeyRef to pull values from a secrets store.

The Pattern

Instead of:

yaml
metadata: - name: redisPassword value: "my-plain-text-password" # BAD: exposed in YAML

Use:

yaml
metadata: - name: redisPassword secretKeyRef: name: redis-password # Kubernetes secret name key: password # Key within the secret

Complete Example: Redis State Store with Secret Password

yaml
# components/statestore.yaml apiVersion: dapr.io/v1alpha1 kind: Component metadata: name: statestore namespace: default spec: type: state.redis version: v1 metadata: - name: redisHost value: redis-master.default.svc.cluster.local:6379 - name: redisPassword secretKeyRef: name: redis-password key: password auth: secretStore: kubernetes-secrets

The auth.secretStore field tells Dapr which secrets store to use for resolving secretKeyRef values. Without this, Dapr doesn't know where to look up the secret.


Configuration API Overview

Secrets are for sensitive data that rarely changes. Configuration is for dynamic settings that may change at runtime---feature flags, rate limits, threshold values.

When to Use Each API

ScenarioUseWhy
Database passwordSecretsSensitive, access-controlled
API keySecretsSensitive, access-controlled
Feature flagConfigurationNon-sensitive, may change frequently
Rate limit valueConfigurationNon-sensitive, may need runtime updates
Service URLConfigurationNon-sensitive, environment-specific
Encryption keySecretsHighly sensitive

Configuration vs Secrets: Key Differences

AspectSecrets APIConfiguration API
PurposeSensitive credentialsDynamic settings
EncryptionAt rest (depends on store)Not required
CachingTypically cachedCan subscribe to changes
Access patternRead on startupRead + subscribe
ExamplesPasswords, API keys, certificatesFeature flags, thresholds

Practical Integration: Task API with Secrets

Let's integrate secrets into the Task API from earlier chapters.

The Scenario

Your Task API needs:

  1. API key for an external notification service
  2. Redis password for state store (via secretKeyRef)

Step 1: Create the Secret

bash
kubectl create secret generic notification-api \ --from-literal=api-key=notif-key-abc123

Step 2: Update Your FastAPI Application

python
from contextlib import asynccontextmanager from fastapi import FastAPI, HTTPException from dapr.clients.aio import DaprClient from pydantic import BaseModel import json class NotificationConfig: api_key: str | None = None notification_config = NotificationConfig() @asynccontextmanager async def lifespan(app: FastAPI): # Load secrets on startup async with DaprClient() as client: secret = await client.get_secret( store_name='kubernetes-secrets', key='notification-api' ) notification_config.api_key = secret.secret.get('api-key') print(f"Loaded notification API key: {notification_config.api_key[:4]}...") yield app = FastAPI(lifespan=lifespan) @app.post("/tasks/{task_id}/notify") async def notify_task_owner(task_id: str): if not notification_config.api_key: raise HTTPException(status_code=500, detail="Notification service not configured") # Use the API key to call external service return {"status": "notification_sent", "task_id": task_id}

Output (on startup):

text
Loaded notification API key: noti...

Reflect on Your Skill

You built a dapr-deployment skill in earlier lessons. Test and improve it based on what you learned.

Test Your Skill

text
Using my dapr-deployment skill, show me how to retrieve API credentials from Kubernetes secrets using Dapr's async Python client.

Identify Gaps

Ask yourself:

  • Does my skill explain the Kubernetes secrets store component?
  • Does it show how to use secretKeyRef in component YAML?
  • Can it help me decide between Secrets API and Configuration API?

Improve Your Skill

If you found gaps:

text
My dapr-deployment skill is missing secrets management patterns. Update it to include: 1. Kubernetes secrets store component (secretstores.kubernetes) 2. DaprClient.get_secret() async pattern 3. secretKeyRef for referencing secrets in component YAML 4. auth.secretStore field requirement

Try With AI

Prompt 1: Retrieve Secrets in Your Application

text
Configure my Task API to get an API key from Kubernetes secrets via Dapr using the async DaprClient. Requirements: - Secret name: external-service-credentials - Key within secret: api-key - Load on application startup using FastAPI lifespan - Make available to route handlers without re-fetching Show me the complete implementation with error handling.

What you're learning: The startup-load pattern ensures secrets are available throughout your application's lifetime without repeated API calls. The lifespan context manager is the modern FastAPI pattern for initialization.


Prompt 2: Reference Secrets in Component YAML

text
Show me how to reference secrets in a Dapr component YAML using secretKeyRef. I have: - Kubernetes secret: database-credentials - Keys in secret: username, password - Component: state.postgresql Show me the complete component YAML with: 1. Host from plain value 2. Username and password from secretKeyRef 3. The auth.secretStore configuration

What you're learning: The secretKeyRef pattern keeps sensitive data out of your YAML files. The auth.secretStore field is required for Dapr to know which secrets store resolves the references.


Prompt 3: Secrets vs Configuration Decision

text
What's the difference between Dapr's Secrets API and Configuration API? When should I use each? I have these values to manage: - Database connection string with password - Feature flag for new notification system - Maximum retry count for failed API calls - API key for payment processor - Threshold for alert notifications For each, tell me which API to use and why.

What you're learning: Secrets are for sensitive data with access control requirements. Configuration is for dynamic settings that may need runtime updates or subscriptions. Mixing them up creates security risks or unnecessary complexity.

Safety Note: Never log full secret values. The pattern api_key[:4] + "..." shown in this lesson reveals only enough to confirm the right secret was loaded. In production, consider not logging secret prefixes at all.