Documentation
¶
Overview ¶
Package env provides environment variable utilities for Azure Developer CLI (azd) extensions.
This package includes:
- Key Vault reference resolution (ResolveMap, ResolveSlice)
- Format conversion (MapToSlice, SliceToMap)
- Pattern-based extraction (FilterByPrefix, ExtractPattern)
- Service name normalization (NormalizeServiceName)
Key Vault Resolution ¶
Use ResolveMap to resolve Azure Key Vault references in environment maps:
import (
"github.com/jongio/azd-core/env"
"github.com/jongio/azd-core/keyvault"
)
resolver, err := keyvault.NewKeyVaultResolver()
if err != nil {
return err
}
envMap := map[string]string{
"DATABASE_URL": "postgres://localhost/db",
"API_KEY": "@Microsoft.KeyVault(VaultName=myvault;SecretName=api-key)",
}
resolved, warnings, err := env.ResolveMap(ctx, envMap, resolver, keyvault.ResolveEnvironmentOptions{})
if err != nil {
return err
}
// resolved["API_KEY"] now contains the actual secret value from Key Vault
Pattern-Based Extraction ¶
Extract environment variables matching specific patterns:
// Filter by prefix (case-insensitive)
azureVars := env.FilterByPrefix(envVars, "AZURE_")
// Returns: {"AZURE_TENANT_ID": "xyz", "AZURE_CLIENT_ID": "abc"}
// Extract SERVICE_*_URL with normalization
serviceURLs := env.ExtractPattern(envVars, env.PatternOptions{
Prefix: "SERVICE_",
Suffix: "_URL",
TrimPrefix: true,
TrimSuffix: true,
Transform: env.NormalizeServiceName,
})
// Returns: {"my-api": "https://...", "web-app": "https://..."}
Service Name Normalization ¶
Convert environment variable naming to service naming conventions:
serviceName := env.NormalizeServiceName("MY_API_SERVICE")
// Returns: "my-api-service"
This is useful for converting uppercase underscore-separated names (common in environment variables) to lowercase hyphen-separated names (common in service identifiers, DNS labels, and container names).
Supported Key Vault Reference Formats ¶
- @Microsoft.KeyVault(SecretUri=https://...)
- @Microsoft.KeyVault(VaultName=...;SecretName=...;SecretVersion=...)
- akvs://<subscription-id>/<vault-name>/<secret-name>[/<version>]
Authentication ¶
Key Vault resolution uses azidentity.DefaultAzureCredential, which supports:
- Environment variables (AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET)
- Managed identity (Azure VM, App Service, Container Apps)
- Azure CLI (az login)
- Azure PowerShell
- Interactive browser authentication
Error Handling ¶
By default, resolution continues even if individual references fail (warnings are collected). Use StopOnError to fail fast:
opts := keyvault.ResolveEnvironmentOptions{StopOnError: true}
resolved, warnings, err := env.ResolveMap(ctx, envMap, resolver, opts)
if err != nil {
// First error encountered
}
Package env provides environment variable resolution utilities with Azure Key Vault integration.
This package makes it easy for consumers (like azd-app and azd-exec) to resolve Azure Key Vault references in environment variables. It provides adapter functions to work with both map[string]string and []string representations of environment variables.
Usage with Environment Maps ¶
Use ResolveMap when working with environment maps:
resolver, err := keyvault.NewKeyVaultResolver()
if err != nil {
// handle error
}
envMap := map[string]string{
"DATABASE_URL": "postgres://localhost/db",
"API_KEY": "@Microsoft.KeyVault(VaultName=myvault;SecretName=api-key)",
}
resolved, warnings, err := env.ResolveMap(ctx, envMap, resolver, keyvault.ResolveEnvironmentOptions{})
if err != nil {
// handle error
}
for _, w := range warnings {
// log warning: w.Key, w.Err
}
// resolved["API_KEY"] now contains the actual secret value from Key Vault
Usage with Environment Slices ¶
Use ResolveSlice when working with KEY=VALUE slices (e.g., from os.Environ()):
resolver, err := keyvault.NewKeyVaultResolver()
if err != nil {
// handle error
}
envSlice := os.Environ() // or []string{"KEY=value", ...}
resolved, warnings, err := env.ResolveSlice(ctx, envSlice, resolver, keyvault.ResolveEnvironmentOptions{})
if err != nil {
// handle error
}
// Use resolved with exec.Cmd: cmd.Env = resolved
Error Handling Options ¶
By default, resolution continues even if individual references fail (warnings are collected). Use StopOnError to fail fast:
opts := keyvault.ResolveEnvironmentOptions{StopOnError: true}
resolved, warnings, err := env.ResolveMap(ctx, envMap, resolver, opts)
if err != nil {
// Resolution failed, warnings contains details
}
Supported Key Vault Reference Formats ¶
The package supports three Key Vault reference formats:
- @Microsoft.KeyVault(SecretUri=https://vault.vault.azure.net/secrets/name/version)
- @Microsoft.KeyVault(VaultName=vault;SecretName=name;SecretVersion=version)
- akvs://guid/vault/secret/version
Helper Functions ¶
The package also provides utility functions for working with environment variables:
- MapToSlice: Convert map[string]string to []string (KEY=VALUE format)
- SliceToMap: Convert []string to map[string]string (skips malformed entries)
- HasKeyVaultReferences: Check if any Key Vault references exist
Index ¶
- func ExtractPattern(envVars map[string]string, opts PatternOptions) map[string]string
- func FilterByPrefix(envVars map[string]string, prefix string) map[string]string
- func FilterByPrefixSlice(envSlice []string, prefix string) []string
- func HasKeyVaultReferences(envVars []string) bool
- func MapToSlice(env map[string]string) []string
- func NormalizeServiceName(envVarName string) string
- func Resolve(ctx context.Context, env map[string]string, resolver Resolver, ...) (map[string]string, []keyvault.KeyVaultResolutionWarning, error)
- func ResolveMap(ctx context.Context, envMap map[string]string, resolver Resolver, ...) (map[string]string, []keyvault.KeyVaultResolutionWarning, error)
- func ResolveSlice(ctx context.Context, envSlice []string, resolver Resolver, ...) ([]string, []keyvault.KeyVaultResolutionWarning, error)
- func SliceToMap(envSlice []string) map[string]string
- type PatternOptions
- type Resolver
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExtractPattern ¶ added in v0.3.0
func ExtractPattern(envVars map[string]string, opts PatternOptions) map[string]string
ExtractPattern extracts environment variables matching prefix/suffix with key transformation. Pattern matching is case-insensitive. Returns a new map with transformed keys.
Example:
envVars := map[string]string{
"SERVICE_API_URL": "https://api.example.com",
"SERVICE_WEB_URL": "https://web.example.com",
"SERVICE_DB_HOST": "db.example.com",
}
// Extract all SERVICE_*_URL variables and normalize service names
urls := env.ExtractPattern(envVars, env.PatternOptions{
Prefix: "SERVICE_",
Suffix: "_URL",
TrimPrefix: true,
TrimSuffix: true,
Transform: func(s string) string { return strings.ToLower(strings.ReplaceAll(s, "_", "-")) },
})
// Returns: {"api": "https://api.example.com", "web": "https://web.example.com"}
func FilterByPrefix ¶ added in v0.3.0
FilterByPrefix returns environment variables matching a prefix. The prefix matching is case-insensitive for keys. Returns a new map containing only the matching entries.
Example:
envVars := map[string]string{
"AZURE_TENANT_ID": "xyz",
"AZURE_CLIENT_ID": "abc",
"DATABASE_URL": "postgres://...",
}
azureVars := env.FilterByPrefix(envVars, "AZURE_")
// Returns: {"AZURE_TENANT_ID": "xyz", "AZURE_CLIENT_ID": "abc"}
func FilterByPrefixSlice ¶ added in v0.3.0
FilterByPrefixSlice returns KEY=VALUE pairs matching a prefix. The prefix matching is case-insensitive for keys. Returns a new slice containing only the matching entries. Malformed entries (without "=") are skipped.
Example:
envSlice := []string{
"AZURE_TENANT_ID=xyz",
"AZURE_CLIENT_ID=abc",
"DATABASE_URL=postgres://...",
}
azureVars := env.FilterByPrefixSlice(envSlice, "AZURE_")
// Returns: ["AZURE_TENANT_ID=xyz", "AZURE_CLIENT_ID=abc"]
func HasKeyVaultReferences ¶
HasKeyVaultReferences quickly checks for any key vault formatted values.
func MapToSlice ¶
MapToSlice converts an env map into KEY=VALUE entries.
func NormalizeServiceName ¶ added in v0.3.0
NormalizeServiceName converts environment variable naming to service naming. Converts uppercase underscore-separated names to lowercase hyphen-separated names. Commonly used with ExtractPattern to normalize service names from environment variables.
Example:
name := env.NormalizeServiceName("MY_API_SERVICE")
// Returns: "my-api-service"
name = env.NormalizeServiceName("WEB_APP")
// Returns: "web-app"
func Resolve ¶
func Resolve(ctx context.Context, env map[string]string, resolver Resolver, opts keyvault.ResolveEnvironmentOptions) (map[string]string, []keyvault.KeyVaultResolutionWarning, error)
Resolve applies a key vault resolver to the provided env map if needed.
func ResolveMap ¶
func ResolveMap(ctx context.Context, envMap map[string]string, resolver Resolver, opts keyvault.ResolveEnvironmentOptions) (map[string]string, []keyvault.KeyVaultResolutionWarning, error)
ResolveMap applies the Key Vault resolver to an environment map. It converts the map to a slice, resolves any Key Vault references, and returns a new map with the resolved values. If resolver is nil or no Key Vault references are found, the original map is returned (as a copy).
This is the primary helper for consumers like azd-app and azd-exec that work with environment maps (e.g., from os.Environ() converted to a map).
Example usage:
resolver, err := keyvault.NewKeyVaultResolver()
if err != nil {
// handle error
}
envMap := map[string]string{
"DATABASE_URL": "postgres://localhost/db",
"API_KEY": "@Microsoft.KeyVault(VaultName=myvault;SecretName=api-key)",
}
resolved, warnings, err := env.ResolveMap(ctx, envMap, resolver, keyvault.ResolveEnvironmentOptions{})
if err != nil {
// handle error
}
for _, w := range warnings {
// log warning: w.Key, w.Err
}
// resolved["API_KEY"] now contains the actual secret value
func ResolveSlice ¶
func ResolveSlice(ctx context.Context, envSlice []string, resolver Resolver, opts keyvault.ResolveEnvironmentOptions) ([]string, []keyvault.KeyVaultResolutionWarning, error)
ResolveSlice applies the Key Vault resolver to an environment slice. It takes KEY=VALUE entries, resolves any Key Vault references, and returns a new slice with the resolved values. If resolver is nil or no Key Vault references are found, the original slice is returned (as a copy).
This is useful for consumers that work directly with environment slices (e.g., from os.Environ() or for passing to exec.Cmd.Env).
Example usage:
resolver, err := keyvault.NewKeyVaultResolver()
if err != nil {
// handle error
}
envSlice := []string{
"DATABASE_URL=postgres://localhost/db",
"API_KEY=@Microsoft.KeyVault(VaultName=myvault;SecretName=api-key)",
}
resolved, warnings, err := env.ResolveSlice(ctx, envSlice, resolver, keyvault.ResolveEnvironmentOptions{})
if err != nil {
// handle error
}
for _, w := range warnings {
// log warning: w.Key, w.Err
}
// resolved can now be used with cmd.Env = resolved
func SliceToMap ¶
SliceToMap converts KEY=VALUE entries into a map, skipping malformed rows.
Types ¶
type PatternOptions ¶ added in v0.3.0
type PatternOptions struct {
// Prefix is the required prefix for keys (e.g., "SERVICE_")
Prefix string
// Suffix is the optional suffix for keys (e.g., "_URL")
Suffix string
// TrimPrefix removes the prefix from result keys if true
TrimPrefix bool
// TrimSuffix removes the suffix from result keys if true
TrimSuffix bool
// Transform is an optional key transformation function applied after trimming
// Example: func(s string) string { return strings.ToLower(s) }
Transform func(string) string
// Validator is an optional value validation function
// If provided, only entries where Validator(value) returns true are included
// Example: func(v string) bool { return v != "" }
Validator func(string) bool
}
PatternOptions configures pattern-based environment variable extraction.