shared-secrets-consumer 0.0.1
Python client for accessing shared secrets across AWS accounts
License: MIT
Requires Python: >=3.10
Keywords: aws, secrets, cross-account, secretsmanager, security

# Shared Secrets Consumer

A Python client library for accessing shared secrets managed by the Shared Secrets Manager across AWS accounts. This library provides a simple interface for cross-account secret discovery and retrieval with built-in caching and error handling.

## Features

- **Cross-Account Access**: Seamlessly access secrets stored in different AWS accounts
- **Automatic Discovery**: Discover secret ARNs using discovery roles and SSM Parameter Store
- **Caching**: Built-in TTL-based caching for improved performance
- **Retry Logic**: Automatic retries with exponential backoff for transient failures
- **Health Monitoring**: Built-in health checks and diagnostics
- **Context Manager**: Automatic cache cleanup when used with `with` statements
- **Batch Operations**: Efficiently retrieve multiple secrets in a single operation

## Installation

```bash
pip install shared-secrets-consumer
```

## Quick Start

### Basic Usage

```python
from shared_secrets_consumer import SharedSecretsClient

# Initialize the client
client = SharedSecretsClient(
    provider_account_id='123456789012',
    product='data-platform'
)

# Get a single secret
db_credentials = client.get_secret('database-credentials')
print(f"Database URL: {db_credentials['url']}")

# Get multiple secrets
secrets = client.get_secrets(['database-credentials', 'api-keys'])
for name, value in secrets.items():
    print(f"Secret {name}: {value}")
```

### Context Manager (Recommended)

```python
with SharedSecretsClient(
    provider_account_id='123456789012',
    product='production'
) as client:
    secret = client.get_secret('my-secret')
    # Cache is automatically cleared when exiting the context
```

### Convenience Functions

```python
from shared_secrets_consumer import get_secret, get_secrets

# Quick single secret access
secret = get_secret(
    secret_name='my-secret',
    provider_account_id='123456789012',
    product='production'
)

# Quick multiple secrets access
secrets = get_secrets(
    secret_names=['secret1', 'secret2'],
    provider_account_id='123456789012',
    product='production'
)
```

## Configuration

### Client Configuration

```python
from shared_secrets_consumer import SharedSecretsClient, ClientConfig

config = ClientConfig(
    provider_account_id='123456789012',
    product='production',
    aws_region='eu-west-1',
    cache_ttl_seconds=600,  # 10 minutes
    max_retries=5,
    enable_caching=True
)

client = SharedSecretsClient(config=config)
```

### Available Configuration Options

- `provider_account_id` (required): AWS account ID where secrets are stored
- `product` (default: 'global'): Product/environment identifier
- `aws_region` (default: 'eu-west-1'): AWS region for secret operations
- `aws_profile` (optional): AWS profile to use for authentication
- `cache_ttl_seconds` (default: 300): Cache time-to-live in seconds
- `max_retries` (default: 3): Maximum number of retry attempts
- `retry_delay_seconds` (default: 1): Base delay between retries
- `enable_caching` (default: True): Enable/disable caching
- `auto_refresh_cache` (default: True): Automatically refresh expired cache entries

## Authentication

The client uses the standard AWS credential chain:

1. AWS profile (if specified in configuration)
2. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
3. IAM instance/container roles
4. AWS SSO credentials

## Error Handling

The library defines specific exception types for different scenarios:

```python
from shared_secrets_consumer import (
    SharedSecretsError,
    SecretNotFoundError,
    SecretAccessDeniedError,
    DiscoveryError
)

try:
    secret = client.get_secret('my-secret')
except SecretNotFoundError:
    print("Secret does not exist")
except SecretAccessDeniedError:
    print("Access denied to secret")
except DiscoveryError:
    print("Failed to discover secret ARN")
except SharedSecretsError as e:
    print(f"General error: {e}")
```

## Advanced Usage

### Health Checks

```python
health = client.health_check()
print(f"Status: {health['status']}")
print(f"Checks: {health['checks']}")
```

### Cache Management

```python
# Get cache statistics
stats = client.get_cache_stats()
print(f"Cached secrets: {stats['total_cached_secrets']}")

# Refresh a specific secret
fresh_secret = client.refresh_secret('my-secret')

# Clear all cached data
client.clear_cache()
```

### List Cached Secrets

```python
# Get list of cached secret names
secret_names = client.list_secrets()

# Get detailed information about cached secrets
secret_info = client.list_secrets(include_metadata=True)
for info in secret_info:
    print(f"Secret: {info.name}, Last accessed: {info.last_accessed}")
```

## Architecture

The library implements a two-stage cross-account access pattern:

1. **Discovery Phase**: Uses discovery roles to find secret ARNs via SSM Parameter Store
   - Discovery role: `arn:aws:iam::{provider_account}:role/SecretDiscovery-{product}-{secret_name}`
   - External ID: `discovery-{product}-{secret_name}`
   - Parameter path: `/shared/secrets/{product}/{secret_name}/arn`

2. **Access Phase**: Direct secret access using resource-based policies with discovered ARNs

## Requirements

- Python 3.10+
- boto3 >= 1.26.0
- botocore >= 1.29.0

## Development

### Setting up Development Environment

```bash
# Clone the repository
git clone https://github.com/hollandcasino/shared-secrets-consumer.git
cd shared-secrets-consumer

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run linting
black src/ tests/
isort src/ tests/
flake8 src/ tests/
mypy src/
```

### Running Tests

```bash
# Run all tests
pytest

# Run only unit tests
pytest -m unit

# Run with coverage
pytest --cov=shared_secrets_consumer --cov-report=html
```

## License

MIT License - see LICENSE file for details.

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests for new functionality
5. Ensure all tests pass
6. Submit a pull request

## Support

For issues and questions, please use the GitHub issue tracker.