# nu_plugin_kms - Verification and Testing Guide

**Date**: 2025-10-08
**Status**: Ready for Testing

## Quick Verification

### 1. Verify Binary Exists

```bash
cd /Users/Akasha/project-provisioning/provisioning/core/plugins/nushell-plugins/nu_plugin_kms

# Check binary exists
ls -lh target/release/nu_plugin_kms

# Expected output:
# -rwxr-xr-x  1 user  staff   X.XM Oct  8 XX:XX target/release/nu_plugin_kms
```

### 2. Register Plugin with Nushell

```bash
# Register plugin
nu -c "plugin add target/release/nu_plugin_kms"

# Verify registration
nu -c "plugin list | where name =~ kms"

# Expected output shows commands:
# - kms encrypt
# - kms decrypt
# - kms generate-key
# - kms status
```

### 3. Test Plugin Help

```bash
# Check command help
nu -c "kms encrypt --help"
nu -c "kms decrypt --help"
nu -c "kms generate-key --help"
nu -c "kms status --help"
```

## Backend Testing

### Age Backend (Simplest - No External Dependencies)

#### Setup

```bash
# Install Age (if not already installed)
brew install age  # macOS
# or
apt install age   # Ubuntu/Debian

# Generate Age key
age-keygen -o ~/.age/test-key.txt

# Extract public key
export AGE_RECIPIENT=$(grep "public key:" ~/.age/test-key.txt | cut -d: -f2 | xargs)
export AGE_IDENTITY="$HOME/.age/test-key.txt"

echo "Age Recipient: $AGE_RECIPIENT"
echo "Age Identity: $AGE_IDENTITY"
```

#### Test Encryption

```bash
# Test 1: Encrypt with Age
nu -c "kms encrypt 'Hello, Age!' --backend age --key $AGE_RECIPIENT" > /tmp/encrypted.txt

cat /tmp/encrypted.txt
# Expected: -----BEGIN AGE ENCRYPTED FILE-----
#           base64data...
#           -----END AGE ENCRYPTED FILE-----
```

#### Test Decryption

```bash
# Test 2: Decrypt with Age
nu -c "kms decrypt '$(cat /tmp/encrypted.txt)' --backend age --key $AGE_IDENTITY"

# Expected output: Hello, Age!
```

#### Test Key Generation

```bash
# Test 3: Generate new Age key pair
nu -c "kms generate-key --backend age"

# Expected output (record):
# {
#   plaintext: "AGE-SECRET-KEY-...",
#   ciphertext: "age1..."
# }
```

#### Test Auto-Detection

```bash
# Test 4: Auto-detect Age backend
nu -c "kms status"

# Expected output:
# {
#   backend: "age",
#   available: true,
#   config: "recipient: age1..., identity: set"
# }
```

### RustyVault Backend

#### Setup

```bash
# Start RustyVault in Docker
docker run -d --name rustyvault \
  -p 8200:8200 \
  -e VAULT_DEV_ROOT_TOKEN_ID=test-token \
  tongsuo/rustyvault:latest

# Wait for startup
sleep 5

# Set environment
export RUSTYVAULT_ADDR="http://localhost:8200"
export RUSTYVAULT_TOKEN="test-token"

# Enable Transit engine
docker exec rustyvault \
  vault secrets enable transit

# Create encryption key
docker exec rustyvault \
  vault write -f transit/keys/provisioning-main
```

#### Test Encryption

```bash
# Test 1: Encrypt with RustyVault
nu -c "kms encrypt 'Secret data!' --backend rustyvault --key provisioning-main"

# Expected output: vault:v1:XXXXXXXXXX...
```

#### Test Decryption

```bash
# Test 2: Encrypt and then decrypt
ENCRYPTED=$(nu -c "kms encrypt 'RustyVault test' --backend rustyvault --key provisioning-main")

nu -c "kms decrypt '$ENCRYPTED' --backend rustyvault --key provisioning-main"

# Expected output: RustyVault test
```

#### Test Key Generation

```bash
# Test 3: Generate AES256 data key
nu -c "kms generate-key --backend rustyvault --spec AES256"

# Expected output (record):
# {
#   plaintext: "base64-encoded-key",
#   ciphertext: "vault:v1:..."
# }
```

#### Test Status

```bash
# Test 4: Check RustyVault status
nu -c "kms status"

# Expected output:
# {
#   backend: "rustyvault",
#   available: true,
#   config: "addr: http://localhost:8200"
# }
```

#### Cleanup

```bash
# Stop and remove RustyVault container
docker stop rustyvault
docker rm rustyvault
```

### HTTP Fallback Backend

#### Setup (Mock Server)

```bash
# Create simple mock KMS server with Python
cat > /tmp/mock_kms_server.py << 'EOF'
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import base64

class KMSHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        body = self.rfile.read(content_length)
        data = json.loads(body)

        if self.path == '/api/v1/kms/encrypt':
            # Simple XOR "encryption"
            plaintext = base64.b64decode(data['plaintext'])
            ciphertext = base64.b64encode(bytes(b ^ 0x42 for b in plaintext)).decode()
            response = {'ciphertext': ciphertext}

        elif self.path == '/api/v1/kms/decrypt':
            # Simple XOR "decryption"
            ciphertext = base64.b64decode(data['ciphertext'])
            plaintext = base64.b64encode(bytes(b ^ 0x42 for b in ciphertext)).decode()
            response = {'plaintext': plaintext}

        elif self.path == '/api/v1/kms/generate-data-key':
            # Generate random key
            import secrets
            key = secrets.token_bytes(32)
            plaintext = base64.b64encode(key).decode()
            ciphertext = base64.b64encode(bytes(b ^ 0x42 for b in key)).decode()
            response = {'plaintext': plaintext, 'ciphertext': ciphertext}
        else:
            self.send_response(404)
            self.end_headers()
            return

        self.send_response(200)
        self.send_header('Content-Type', 'application/json')
        self.end_headers()
        self.wfile.write(json.dumps(response).encode())

if __name__ == '__main__':
    server = HTTPServer(('localhost', 8081), KMSHandler)
    print('Mock KMS server running on http://localhost:8081')
    server.serve_forever()
EOF

chmod +x /tmp/mock_kms_server.py

# Start mock server in background
python3 /tmp/mock_kms_server.py &
MOCK_SERVER_PID=$!

# Set environment
export KMS_HTTP_URL="http://localhost:8081"
export KMS_HTTP_BACKEND="mock"
```

#### Test HTTP Backend

```bash
# Test 1: Encrypt
nu -c "kms encrypt 'HTTP test data' --backend mock"

# Test 2: Encrypt and decrypt
ENCRYPTED=$(nu -c "kms encrypt 'Round trip test' --backend mock")
nu -c "kms decrypt '$ENCRYPTED' --backend mock"

# Test 3: Generate key
nu -c "kms generate-key --backend mock --spec AES256"

# Test 4: Status
nu -c "kms status"
```

#### Cleanup

```bash
# Stop mock server
kill $MOCK_SERVER_PID
```

## Integration Tests

### Test Auto-Detection Priority

```bash
# Test 1: RustyVault has priority
export RUSTYVAULT_ADDR="http://localhost:8200"
export RUSTYVAULT_TOKEN="test-token"
export AGE_RECIPIENT="age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"

nu -c "kms status"
# Expected: backend = "rustyvault"

# Test 2: Age when RustyVault not set
unset RUSTYVAULT_ADDR
unset RUSTYVAULT_TOKEN

nu -c "kms status"
# Expected: backend = "age"

# Test 3: HTTP fallback when nothing set
unset AGE_RECIPIENT

nu -c "kms status"
# Expected: backend = "cosmian" (or configured HTTP backend)
```

### Test Error Handling

```bash
# Test 1: Missing required flags
nu -c "kms encrypt 'data' --backend age"
# Expected: Error about missing --key recipient

# Test 2: Invalid recipient format
nu -c "kms encrypt 'data' --backend age --key invalid"
# Expected: Error about invalid Age recipient format

# Test 3: Missing environment variable
unset RUSTYVAULT_TOKEN
nu -c "kms encrypt 'data' --backend rustyvault"
# Expected: Error about RUSTYVAULT_TOKEN not set

# Test 4: Invalid key spec
nu -c "kms generate-key --backend rustyvault --spec INVALID"
# Expected: Error about invalid key spec
```

### Test Binary Data

```bash
# Test handling of non-UTF8 data
dd if=/dev/urandom bs=1024 count=1 | base64 > /tmp/random.b64

# Encrypt binary data
ENCRYPTED=$(cat /tmp/random.b64 | nu -c "kms encrypt $in --backend age --key $AGE_RECIPIENT")

# Decrypt and compare
DECRYPTED=$(nu -c "kms decrypt '$ENCRYPTED' --backend age --key $AGE_IDENTITY")

# Verify round-trip
if [ "$(cat /tmp/random.b64)" = "$DECRYPTED" ]; then
  echo "✅ Binary data round-trip successful"
else
  echo "❌ Binary data round-trip failed"
fi
```

## Performance Benchmarks

### Age Performance

```bash
# Benchmark encryption (1000 iterations)
time for i in {1..1000}; do
  nu -c "kms encrypt 'test data' --backend age --key $AGE_RECIPIENT" > /dev/null
done

# Expected: ~10-20ms per operation
```

### RustyVault Performance

```bash
# Benchmark encryption (1000 iterations)
time for i in {1..1000}; do
  nu -c "kms encrypt 'test data' --backend rustyvault --key provisioning-main" > /dev/null
done

# Expected: ~20-50ms per operation (includes HTTP overhead)
```

### Memory Usage

```bash
# Monitor memory during operations
while true; do
  nu -c "kms encrypt 'test data' --backend age --key $AGE_RECIPIENT" > /dev/null
  ps aux | grep nu_plugin_kms | grep -v grep
  sleep 1
done

# Expected: Stable memory usage, no leaks
```

## Verification Checklist

### Compilation
- [x] `cargo check` passes
- [x] `cargo build --release` succeeds
- [x] Binary created in `target/release/nu_plugin_kms`
- [x] File size reasonable (< 50MB)

### Plugin Registration
- [ ] Plugin registers with Nushell
- [ ] All 4 commands visible in `plugin list`
- [ ] Help text accessible for each command

### Age Backend
- [ ] Encryption works with recipient
- [ ] Decryption works with identity file
- [ ] Key generation produces valid key pair
- [ ] Status shows correct backend
- [ ] Auto-detection works when env vars set

### RustyVault Backend
- [ ] Encryption works with Transit engine
- [ ] Decryption works correctly
- [ ] Data key generation works
- [ ] Status shows correct backend
- [ ] Auto-detection works when env vars set

### HTTP Fallback
- [ ] Encryption works with HTTP service
- [ ] Decryption works correctly
- [ ] Data key generation works
- [ ] Status shows correct backend
- [ ] Auto-detection works as fallback

### Error Handling
- [ ] Missing flags produce clear errors
- [ ] Invalid inputs rejected gracefully
- [ ] Network errors handled properly
- [ ] Missing env vars reported clearly

### Integration
- [ ] Auto-detection priority correct
- [ ] Multiple backends can coexist
- [ ] Environment switching works
- [ ] Binary data handled correctly

## Success Criteria

✅ **Basic Functionality**
- All backends encrypt and decrypt successfully
- Key generation works for all backends
- Status command reports correctly

✅ **Robustness**
- Error messages are clear and actionable
- No panics or crashes
- Memory usage is stable

✅ **Performance**
- Operations complete in reasonable time
- No memory leaks
- Concurrent operations work

✅ **Usability**
- Auto-detection works as expected
- Environment configuration is straightforward
- Help text is clear

## Troubleshooting

### Plugin Not Loading

```bash
# Check plugin is registered
nu -c "plugin list" | grep kms

# If not registered, add it
nu -c "plugin add /path/to/nu_plugin_kms"

# Check for errors
nu -c "plugin list --version"
```

### Environment Variables Not Working

```bash
# Check env vars are set
env | grep -E '(RUSTYVAULT|AGE|KMS)'

# Test in new shell
bash -c 'export AGE_RECIPIENT=...; nu -c "kms status"'
```

### Compilation Errors

```bash
# Clean build
cargo clean

# Update dependencies
cargo update

# Rebuild
cargo build --release
```

## Next Steps

After successful verification:

1. **Documentation**: Update user guides with examples
2. **Integration**: Connect to config encryption module
3. **CI/CD**: Add automated tests to pipeline
4. **Deployment**: Package for distribution
5. **Monitoring**: Add telemetry and logging
