chore: Enhance documentation for E2E testing:
- Added clarity and structure to README files, including recent updates and getting started sections. - Improved manual verification documentation for CrowdSec authentication, emphasizing expected outputs and success criteria. - Updated debugging guide with detailed output examples and automatic trace capture information. - Refined best practices for E2E tests, focusing on efficient polling, locator strategies, and state management. - Documented triage report for DNS Provider feature tests, highlighting issues fixed and test results before and after improvements. - Revised E2E test writing guide to include when to use specific helper functions and patterns for better test reliability. - Enhanced troubleshooting documentation with clear resolutions for common issues, including timeout and token configuration problems. - Updated tests README to provide quick links and best practices for writing robust tests.
This commit is contained in:
@@ -23,6 +23,7 @@ Authorization: Bearer your-api-token-here
|
||||
```
|
||||
|
||||
Tokens support granular permissions:
|
||||
|
||||
- **Read-only**: View configurations without modification
|
||||
- **Full access**: Complete CRUD operations
|
||||
- **Scoped**: Limit to specific resource types
|
||||
|
||||
@@ -52,6 +52,7 @@ Caddyfile import parses your existing Caddy configuration files and converts the
|
||||
Choose one of three methods:
|
||||
|
||||
**Paste Content:**
|
||||
|
||||
```
|
||||
example.com {
|
||||
reverse_proxy localhost:3000
|
||||
@@ -63,10 +64,12 @@ api.example.com {
|
||||
```
|
||||
|
||||
**Upload File:**
|
||||
|
||||
- Click **Choose File**
|
||||
- Select your Caddyfile
|
||||
|
||||
**Fetch from URL:**
|
||||
|
||||
- Enter URL to raw Caddyfile content
|
||||
- Useful for version-controlled configurations
|
||||
|
||||
|
||||
@@ -447,6 +447,7 @@ Charon displays instructions to remove the TXT record after certificate issuance
|
||||
**Symptom**: Certificate request stuck at "Waiting for Propagation" or validation fails.
|
||||
|
||||
**Causes**:
|
||||
|
||||
- DNS TTL is high (cached old records)
|
||||
- DNS provider has slow propagation
|
||||
- Regional DNS inconsistency
|
||||
@@ -497,6 +498,7 @@ Charon displays instructions to remove the TXT record after certificate issuance
|
||||
**Symptom**: Connection test passes, but record creation fails.
|
||||
|
||||
**Causes**:
|
||||
|
||||
- API token has read-only permissions
|
||||
- Zone/domain not accessible with current credentials
|
||||
- Rate limiting or account restrictions
|
||||
@@ -513,6 +515,7 @@ Charon displays instructions to remove the TXT record after certificate issuance
|
||||
**Symptom**: "Record already exists" error during certificate request.
|
||||
|
||||
**Causes**:
|
||||
|
||||
- Previous challenge attempt left orphaned record
|
||||
- Manual DNS record with same name exists
|
||||
- Another ACME client managing the same domain
|
||||
@@ -551,6 +554,7 @@ Charon displays instructions to remove the TXT record after certificate issuance
|
||||
**Symptom**: "Too many requests" or "Rate limit exceeded" errors.
|
||||
|
||||
**Causes**:
|
||||
|
||||
- Too many certificate requests in short period
|
||||
- DNS provider API rate limits
|
||||
- Let's Encrypt rate limits
|
||||
|
||||
@@ -47,6 +47,7 @@ Docker auto-discovery eliminates manual IP address hunting and port memorization
|
||||
For Charon to discover containers, it needs Docker API access.
|
||||
|
||||
**Docker Compose:**
|
||||
|
||||
```yaml
|
||||
services:
|
||||
charon:
|
||||
@@ -56,6 +57,7 @@ services:
|
||||
```
|
||||
|
||||
**Docker Run:**
|
||||
|
||||
```bash
|
||||
docker run -v /var/run/docker.sock:/var/run/docker.sock:ro charon
|
||||
```
|
||||
|
||||
@@ -35,18 +35,21 @@ CHARON_PLUGIN_SIGNATURES='{"pluginname": "sha256:..."}'
|
||||
### Examples
|
||||
|
||||
**Permissive mode (default)**:
|
||||
|
||||
```bash
|
||||
# Unset — all plugins load without verification
|
||||
unset CHARON_PLUGIN_SIGNATURES
|
||||
```
|
||||
|
||||
**Strict block-all**:
|
||||
|
||||
```bash
|
||||
# Empty object — no external plugins will load
|
||||
export CHARON_PLUGIN_SIGNATURES='{}'
|
||||
```
|
||||
|
||||
**Allowlist specific plugins**:
|
||||
|
||||
```bash
|
||||
# Only powerdns and custom-provider plugins are allowed
|
||||
export CHARON_PLUGIN_SIGNATURES='{"powerdns": "sha256:a1b2c3d4...", "custom-provider": "sha256:e5f6g7h8..."}'
|
||||
@@ -63,6 +66,7 @@ sha256sum myplugin.so | awk '{print "sha256:" $1}'
|
||||
```
|
||||
|
||||
**Example output**:
|
||||
|
||||
```
|
||||
sha256:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2
|
||||
```
|
||||
@@ -96,6 +100,7 @@ services:
|
||||
```
|
||||
|
||||
This prevents runtime modification of plugin files, mitigating:
|
||||
|
||||
- Time-of-check to time-of-use (TOCTOU) attacks
|
||||
- Malicious plugin replacement after signature verification
|
||||
|
||||
@@ -113,6 +118,7 @@ services:
|
||||
```
|
||||
|
||||
Or in Dockerfile:
|
||||
|
||||
```dockerfile
|
||||
FROM charon:latest
|
||||
USER charon
|
||||
@@ -128,6 +134,7 @@ Plugin directories must **not** be world-writable. Charon enforces this at start
|
||||
| `0777` (world-writable) | ❌ Rejected — plugin loading disabled |
|
||||
|
||||
**Set secure permissions**:
|
||||
|
||||
```bash
|
||||
chmod 755 /path/to/plugins
|
||||
chmod 644 /path/to/plugins/*.so # Or 755 for executable
|
||||
@@ -192,22 +199,26 @@ After updating plugins, always update your `CHARON_PLUGIN_SIGNATURES` with the n
|
||||
### Checking if a Plugin Loaded
|
||||
|
||||
**Check startup logs**:
|
||||
|
||||
```bash
|
||||
docker compose logs charon | grep -i plugin
|
||||
```
|
||||
|
||||
**Expected success output**:
|
||||
|
||||
```
|
||||
INFO Loaded DNS provider plugin type=powerdns name="PowerDNS" version="1.0.0"
|
||||
INFO Loaded 1 external DNS provider plugins (0 failed)
|
||||
```
|
||||
|
||||
**If using allowlist**:
|
||||
|
||||
```
|
||||
INFO Plugin signature allowlist enabled with 2 entries
|
||||
```
|
||||
|
||||
**Via API**:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8080/api/admin/plugins \
|
||||
-H "Authorization: Bearer YOUR-TOKEN"
|
||||
@@ -220,6 +231,7 @@ curl http://localhost:8080/api/admin/plugins \
|
||||
**Cause**: The plugin filename (without `.so`) is not in `CHARON_PLUGIN_SIGNATURES`.
|
||||
|
||||
**Solution**: Add the plugin to your allowlist:
|
||||
|
||||
```bash
|
||||
# Get the signature
|
||||
sha256sum powerdns.so | awk '{print "sha256:" $1}'
|
||||
@@ -233,6 +245,7 @@ export CHARON_PLUGIN_SIGNATURES='{"powerdns": "sha256:YOUR_HASH_HERE"}'
|
||||
**Cause**: The plugin file's SHA-256 hash doesn't match the allowlist.
|
||||
|
||||
**Solution**:
|
||||
|
||||
1. Verify you have the correct plugin file
|
||||
2. Re-compute the signature: `sha256sum plugin.so`
|
||||
3. Update `CHARON_PLUGIN_SIGNATURES` with the correct hash
|
||||
@@ -242,6 +255,7 @@ export CHARON_PLUGIN_SIGNATURES='{"powerdns": "sha256:YOUR_HASH_HERE"}'
|
||||
**Cause**: The plugin directory is world-writable (mode `0777` or similar).
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
chmod 755 /path/to/plugins
|
||||
chmod 644 /path/to/plugins/*.so
|
||||
@@ -252,11 +266,13 @@ chmod 644 /path/to/plugins/*.so
|
||||
**Cause**: Malformed JSON in the environment variable.
|
||||
|
||||
**Solution**: Validate your JSON:
|
||||
|
||||
```bash
|
||||
echo '{"powerdns": "sha256:abc123"}' | jq .
|
||||
```
|
||||
|
||||
Common issues:
|
||||
|
||||
- Missing quotes around keys or values
|
||||
- Trailing commas
|
||||
- Single quotes instead of double quotes
|
||||
@@ -266,6 +282,7 @@ Common issues:
|
||||
**Cause**: File permissions too restrictive or ownership mismatch.
|
||||
|
||||
**Solution**:
|
||||
|
||||
```bash
|
||||
# Check current permissions
|
||||
ls -la /path/to/plugins/
|
||||
@@ -278,27 +295,32 @@ chown charon:charon /path/to/plugins/*.so
|
||||
### Debugging Checklist
|
||||
|
||||
1. **Is the plugin directory configured?**
|
||||
|
||||
```bash
|
||||
echo $CHARON_PLUGINS_DIR
|
||||
```
|
||||
|
||||
2. **Does the plugin file exist?**
|
||||
|
||||
```bash
|
||||
ls -la $CHARON_PLUGINS_DIR/*.so
|
||||
```
|
||||
|
||||
3. **Are directory permissions secure?**
|
||||
|
||||
```bash
|
||||
stat -c "%a %n" $CHARON_PLUGINS_DIR
|
||||
# Should be 755 or stricter
|
||||
```
|
||||
|
||||
4. **Is the signature correct?**
|
||||
|
||||
```bash
|
||||
sha256sum $CHARON_PLUGINS_DIR/myplugin.so
|
||||
```
|
||||
|
||||
5. **Is the JSON valid?**
|
||||
|
||||
```bash
|
||||
echo "$CHARON_PLUGIN_SIGNATURES" | jq .
|
||||
```
|
||||
|
||||
@@ -69,22 +69,26 @@ X-Forwarded-Host preserves the original domain:
|
||||
Your backend must trust proxy headers from Charon. Common configurations:
|
||||
|
||||
**Node.js/Express:**
|
||||
|
||||
```javascript
|
||||
app.set('trust proxy', true);
|
||||
```
|
||||
|
||||
**Django:**
|
||||
|
||||
```python
|
||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||
USE_X_FORWARDED_HOST = True
|
||||
```
|
||||
|
||||
**Rails:**
|
||||
|
||||
```ruby
|
||||
config.action_dispatch.trusted_proxies = [IPAddr.new('10.0.0.0/8')]
|
||||
```
|
||||
|
||||
**PHP/Laravel:**
|
||||
|
||||
```php
|
||||
// In TrustProxies middleware
|
||||
protected $proxies = '*';
|
||||
|
||||
Reference in New Issue
Block a user