secenv 0.0.0

Secure environments.
# secenv

**Secure Environment Variable Management with PGP Encryption**

`secenv` is a command-line tool for managing environment variables with PGP encryption support. It allows you to store sensitive configuration values encrypted in YAML files and decrypt them on-demand using your system's GPG keys.

## Features

- 🔐 **PGP Encryption**: Encrypt sensitive values using OpenPGP/GPG
- 📁 **Profile-Based Configuration**: Organize variables into different profiles (dev, staging, prod, etc.)
- 🔑 **System GPG Integration**: Uses your existing GPG keys and agent
- 🛡️ **Password Protection**: Supports password-protected PGP keys with secure prompting
- 📄 **Multiple Value Types**: Literal values, environment variables, files, and encrypted values
-**Fast & Lightweight**: Written in Rust for performance and safety

## Installation

### From Source

```bash
git clone https://github.com/cchexcode/secenv
cd secenv
cargo build --release
```

The binary will be available at `target/release/secenv`.

## Quick Start

### 1. Create a Configuration File

Create a `secenv.yaml` file with your environment variables:

```yaml
# Define reusable anchors
.defaultkey: &defaultkey "PGP-KEY-FINGERPRINT"

profiles:
  dev:
    propagate: true
    vars:
      # Literal value
      APP_NAME: !literal "myapp"
      # Environment variable reference
      HOME_DIR: !environment "HOME"
      # File content
      CONFIG_JSON_CONTENT: !file "/etc/myapp/config.json"

      # PGP encrypted value
      DATABASE_PASSWORD: !pgp
        key: *defaultkey
        value: |
          -----BEGIN PGP MESSAGE-----
          ...
          -----END PGP MESSAGE-----
  production:
    propagate: false
    vars:
      APP_NAME: !literal "myapp"
      DATABASE_PASSWORD: !pgp
        key: "PROD_KEY_FINGERPRINT"
        value: |
          -----BEGIN PGP MESSAGE-----
          ...
          -----END PGP MESSAGE-----
```

### 2. Encrypt Values

To create encrypted values, use GPG to encrypt your secrets:

```bash
# Encrypt a value for a specific key
echo "my-secret-password" | gpg --encrypt --armor --recipient your@email.com

# Or encrypt for a specific key fingerprint
echo "my-secret-password" | gpg --encrypt --armor --recipient 9CD9D9187E17BE27E2F838B7BA59BCD337CEEA1D
```

Copy the resulting PGP message (including the `-----BEGIN PGP MESSAGE-----` and `-----END PGP MESSAGE-----` lines) into your YAML file.

### 3. Unlock Variables

```bash
# Unlock variables from the default profile
secenv unlock

# Unlock variables from a specific profile
secenv unlock --profile production

# Use a different config file
secenv unlock --config /path/to/config.yaml --profile staging
```

Output format:
```
APP_NAME=MyApp
DATABASE_PASSWORD=my-secret-password
HOME_DIR=/Users/username
```

## Configuration Format

### Profile Structure

```yaml
profiles:
  <profile-name>:
    propagate: <boolean>  # Whether to propagate to child processes
    vars:
      <variable-name>: <value-provider>
```

### Value Providers

#### Literal Values
```yaml
APP_NAME: !literal "MyApplication"
```

#### Environment Variables
```yaml
HOME_DIR: !environment "HOME"
USER_NAME: !environment "USER"
```

#### File Contents
```yaml
CONFIG_DATA: !file "/etc/myapp/config.json"
CERTIFICATE: !file "/etc/ssl/certs/app.crt"
```

#### PGP Encrypted Values
```yaml
SECRET_KEY: !pgp
  key: "9CD9D9187E17BE27E2F838B7BA59BCD337CEEA1D"  # PGP key fingerprint
  value: |
    -----BEGIN PGP MESSAGE-----
    
    hQIMA/nYRg4ylYK0AQ/+K25a1jwIORvRnutLSR4vBuWA1mC8GHDrWRW3k7btX8DD
    ...
    -----END PGP MESSAGE-----
```

### YAML Anchors and References

Use YAML anchors to avoid repeating key fingerprints:

```yaml
.defaultkey: &defaultkey "9CD9D9187E17BE27E2F838B7BA59BCD337CEEA1D"
.prodkey: &prodkey "ABCD1234567890ABCD1234567890ABCD12345678"

profiles:
  default:
    vars:
      SECRET1: !pgp
        key: *defaultkey
        value: "..."
      SECRET2: !pgp
        key: *defaultkey
        value: "..."
  
  production:
    vars:
      SECRET1: !pgp
        key: *prodkey
        value: "..."
```

## Usage

### Commands

#### `unlock`
Decrypt and display environment variables from a profile.

```bash
secenv unlock [OPTIONS]

Options:
  -c, --config <config>    Configuration file path [default: secenv.yaml]
  -p, --profile <profile>  Profile to unlock [default: default]
  -h, --help              Print help
```

#### `man`
Generate manual pages.

```bash
secenv man --out <directory> --format <manpages|markdown>
```

#### `autocomplete`
Generate shell completion scripts.

```bash
secenv autocomplete --out <directory> --shell <bash|zsh|fish|elvish|powershell>
```

### Integration Examples

#### Shell Integration
```bash
# Load variables into current shell
eval "$(secenv unlock --profile production)"

# Export to a file
secenv unlock --profile staging > .env
```

#### Docker Integration
```dockerfile
# In your Dockerfile
COPY secenv.yaml /app/
RUN secenv unlock --profile production > /app/.env
```

#### CI/CD Integration
```yaml
# GitHub Actions example
- name: Load secrets
  run: |
    secenv unlock --profile ci > $GITHUB_ENV
```

## Security Considerations

### PGP Key Management

- **Key Storage**: Store your PGP private keys securely using your system's keychain or GPG agent
- **Key Rotation**: Regularly rotate encryption keys and re-encrypt values
- **Access Control**: Use different PGP keys for different environments (dev, staging, prod)

### Best Practices

1. **Never commit unencrypted secrets** to version control
2. **Use different keys per environment** to limit blast radius
3. **Regularly audit** who has access to decryption keys
4. **Use strong passphrases** for PGP keys
5. **Enable GPG agent** for convenient key management
6. **Backup your keys** securely

### Password-Protected Keys

When using password-protected PGP keys, `secenv` will:

1. Attempt decryption without a password first
2. If that fails, prompt securely for the password
3. Allow up to 3 retry attempts
4. Integrate with GPG agent for cached passwords

## GPG Setup

### Generate a New Key

```bash
# Generate a new GPG key
gpg --full-generate-key

# List your keys
gpg --list-secret-keys --keyid-format LONG

# Export public key (for sharing)
gpg --armor --export your@email.com
```

### Import Existing Keys

```bash
# Import a private key
gpg --import private-key.asc

# Import a public key
gpg --import public-key.asc

# Trust a key
gpg --edit-key your@email.com
# In GPG prompt: trust -> 5 -> y -> quit
```

## Troubleshooting

### Common Issues

#### "GPG decryption failed"
- Ensure the correct PGP key is installed: `gpg --list-secret-keys`
- Verify the key fingerprint matches the one in your config
- Check if the key requires a password and GPG agent is running

#### "Profile not found"
- Verify the profile name exists in your config file
- Check YAML syntax with `yamllint secenv.yaml`

#### "Failed to read config"
- Ensure the config file exists and is readable
- Verify YAML syntax is correct
- Check file permissions

### Debug Mode

For verbose output, set the `RUST_LOG` environment variable:

```bash
RUST_LOG=debug secenv unlock
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

### Development Setup

```bash
git clone https://github.com/cchexcode/secenv
cd secenv
cargo build
cargo test
```

### Running Tests

```bash
# Run all tests
cargo test

# Run with output
cargo test -- --nocapture

# Run specific test
cargo test test_name
```

## License

This project is licensed under the MIT License - see the [LICENSE](../LICENSE) file for details.

## Changelog

### v0.0.0 (Current)
- Initial implementation
- PGP encryption support
- Profile-based configuration
- Multiple value providers (literal, environment, file, pgp)
- GPG integration with password support
- Shell completion and manual generation

## Related Projects

- [sops]https://github.com/mozilla/sops - Secrets OPerationS
- [age]https://github.com/FiloSottile/age - Simple, modern encryption tool
- [pass]https://www.passwordstore.org/ - The standard unix password manager