2 releases
| 0.0.2 | Jun 5, 2025 |
|---|---|
| 0.0.1 | Jun 5, 2025 |
#323 in HTTP client
202 downloads per month
Used in nabla-cli
515KB
8K
SLoC
doppler-rs
Unofficial client library for the Doppler API - secure secrets management platform
🔐 About Doppler
Doppler is a universal secrets manager that helps developers and DevOps teams securely store, manage, and deploy environment variables and secrets across applications, environments, and team members.
✨ Features
- Complete API Coverage: Full support for all Doppler API endpoints
- Type Safety: Leverages Rust's type system for secure and reliable code
- Async/Await: Built on top of
reqwestwith full async support usingtokio - Comprehensive Error Handling: Detailed error types for robust error handling
- Automatic Serialization: JSON serialization/deserialization with
serde - DateTime Support: Native
chronointegration for date/time fields
📦 Installation
Add this to your Cargo.toml:
[dependencies]
doppler-rs = "0.0.2"
tokio = { version = "1.0", features = ["full"] }
Features
This crate supports the following optional features:
rustls (TLS Backend)
Enables rustls-tls for reqwest, providing a pure Rust TLS implementation:
[dependencies]
doppler-rs = { version = "0.0.2", features = ["rustls"] }
When to use rustls:
- You prefer a pure Rust TLS stack
- You want to avoid OpenSSL dependencies
- You're targeting environments where OpenSSL isn't available
- You need reproducible builds across different platforms
Default behavior: Without any features enabled, reqwest will use the system's default TLS implementation (typically OpenSSL on Unix systems and SChannel on Windows).
# Use default TLS (system native)
doppler-rs = "0.0.2"
# Use rustls TLS
doppler-rs = { version = "0.0.2", features = ["rustls"] }
🚀 Quick Start
Authentication
Doppler supports multiple authentication methods:
Service Tokens (Recommended for Applications)
use doppler_rs::{apis::{configuration::Configuration, default_api}, models};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = Configuration::new();
config.bearer_access_token = Some("dp.st.your-service-token".to_string());
// List all secrets for the configured project and environment
let secrets = default_api::secrets_list(
&config,
"your-project",
"your-config",
None, // accepts
None, // include_dynamic_secrets
None, // dynamic_secrets_ttl_sec
None, // secrets
None, // include_managed_secrets
).await?;
println!("Secrets: {:#?}", secrets);
Ok(())
}
Personal Access Tokens
use doppler_rs::{apis::{configuration::Configuration, default_api}};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = Configuration::new();
config.bearer_access_token = Some("dp.pt.your-personal-token".to_string());
// Get current user information
let me = default_api::auth_me(&config).await?;
println!("Current user: {:#?}", me);
Ok(())
}
Managing Secrets
use doppler_rs::{apis::{configuration::Configuration, default_api}, models};
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = Configuration::new();
config.bearer_access_token = Some("dp.st.your-service-token".to_string());
let project = "your-project";
let config_name = "your-config";
// List secrets
let secrets_response = default_api::secrets_list(
&config,
project,
config_name,
None, None, None, None, None
).await?;
if let Some(secrets) = &secrets_response.secrets {
println!("Found secrets in response");
}
// Get a specific secret
let secret = default_api::secrets_get(
&config,
project,
config_name,
"DATABASE_URL"
).await?;
if let Some(value) = &secret.value {
println!("Secret value: {}", value.computed);
}
// Update secrets using the UpdateSecretsRequest model
let mut secrets_map = HashMap::new();
secrets_map.insert("NEW_SECRET".to_string(), "secret-value".to_string());
let mut update_request = models::UpdateSecretsRequest::new(
project.to_string(),
config_name.to_string(),
);
update_request.secrets = Some(secrets_map);
let updated = default_api::secrets_update(&config, Some(update_request)).await?;
println!("Updated secrets: {:#?}", updated);
Ok(())
}
Project and Environment Management
use doppler_rs::{apis::{configuration::Configuration, default_api}, models};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = Configuration::new();
config.bearer_access_token = Some("dp.pt.your-personal-token".to_string());
// List projects
let projects = default_api::projects_list(&config, None, None).await?;
if let Some(projects_list) = &projects.projects {
for project in projects_list {
if let (Some(name), Some(slug)) = (&project.name, &project.slug) {
println!("Project: {} ({})", name, slug);
}
}
}
// Create a new environment
let create_env_request = models::CreateEnvironmentRequest::new(
"staging".to_string(),
"staging".to_string()
);
let new_env = default_api::environments_create(
&config,
"my-project",
Some(create_env_request)
).await?;
println!("Created environment: {:#?}", new_env);
Ok(())
}
Service Account Management
use doppler_rs::{apis::{configuration::Configuration, default_api}, models};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = Configuration::new();
config.bearer_access_token = Some("dp.pt.your-personal-token".to_string());
// List service accounts
let service_accounts = default_api::service_accounts_list(&config, None, None).await?;
if let Some(accounts) = &service_accounts.service_accounts {
for account in accounts {
if let (Some(name), Some(slug)) = (&account.name, &account.slug) {
println!("Service Account: {} ({})", name, slug);
}
}
}
// Create service account token
let mut create_token_request = models::CreateServiceAccountTokenRequest::new(
"CI/CD Token".to_string()
);
create_token_request.config = Some("production".to_string());
let token = default_api::service_account_tokens_create(
&config,
"my-service-account",
Some(create_token_request)
).await?;
if let Some(api_token) = &token.api_token {
println!("Created token: {}", api_token.key);
}
Ok(())
}
📖 API Documentation
This client provides access to all Doppler API endpoints:
Core Resources
- Secrets: Manage environment variables and secrets
- Projects: Organize secrets into projects
- Environments: Separate secrets by environment (dev, staging, prod)
- Configs: Fine-grained secret organization within environments
Access Control
- Users: Manage team members and permissions
- Groups: Organize users into groups with shared permissions
- Service Accounts: Automated access for applications and CI/CD
- Workplace Roles: Define permissions across the organization
- Project Roles: Define permissions within specific projects
Security & Compliance
- Activity Logs: Audit trail of all changes and access
- Config Logs: Detailed history of secret changes
- Trusted IPs: Restrict access by IP address
- Change Request Policies: Require approval for sensitive changes
Integrations
- Webhooks: Real-time notifications of changes
- Syncs: Automatically sync secrets to external services
- Dynamic Secrets: Generate short-lived credentials on-demand
For detailed API documentation, visit: https://docs.doppler.com/reference
🛠️ Configuration
The client uses reqwest with sensible defaults:
use doppler_rs::apis::configuration::Configuration;
let mut config = Configuration::new();
config.bearer_access_token = Some("your-token".to_string());
// Optionally customize other settings
config.user_agent = Some("MyApp/0.0.2".to_string());
Environment Variables
You can also configure the client using environment variables:
export DOPPLER_TOKEN="dp.st.your-service-token"
use doppler_rs::{apis::{configuration::Configuration, default_api}};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut config = Configuration::new();
config.bearer_access_token = std::env::var("DOPPLER_TOKEN").ok();
// Use the configured client
let secrets = default_api::secrets_list(
&config,
"your-project",
"your-config",
None, None, None, None, None
).await?;
Ok(())
}
🔒 Security Best Practices
- Use Service Tokens for Applications: Service tokens are scoped to specific projects/environments
- Rotate Tokens Regularly: Set expiration dates and rotate tokens periodically
- Limit Token Scope: Use the most restrictive token type that meets your needs
- Store Tokens Securely: Never commit tokens to version control
- Use Trusted IPs: Restrict API access to known IP addresses when possible
- Monitor Activity Logs: Regularly review API usage and access patterns
🤝 Contributing
This is a generated API client library. Most improvements come from updates to the OpenAPI specification or the generation templates.
Reporting Issues
If you encounter bugs or have feature requests:
- Check if it's an API issue by testing with the Doppler API directly
- For client-specific issues, please open an issue on GitHub
- Include relevant code examples and error messages
Development Setup
- Clone the repository
- Install Rust (latest stable)
- Run tests:
cargo test - Run examples:
cargo run --example basic_usage
Generating the Client
This client is generated from the Doppler OpenAPI specification:
# Regenerate the client
./generate_with_chrono.sh
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
- Documentation: https://docs.doppler.com
- Community: https://community.doppler.com
- Issues: Please open an issue on GitHub
- Security: For security issues related to the doppler api and not this crate, email security@doppler.com
🏷️ Version
Current Version: 0.0.2
Generated with: OpenAPI Generator
Disclaimer: This is an unofficial client library. For official SDKs and support, visit Doppler's official documentation.
Dependencies
~9–16MB
~280K SLoC