Chef Server Integration Testing Guide#
This guide explains how to test the authenticated Chef Server integration with a live Chef Server, including secrets redaction functionality.
NOTE: Testing Without Chef Server? See Mock Chef Server Testing Guide for testing with mocked HTTP responses - no Chef Server required!
Quick Links#
- Mock Testing Guide - Test without a real Chef Server (recommended for development)
- Unit tests -
tests/unit/test_chef_server_client.py(repository source) - Mock integration tests -
tests/integration/test_chef_server_mock.py(repository source) - This Guide - Testing with a live Chef Server instance
Prerequisites#
- Chef Server Access: You need access to a Chef Server instance (Chef Infra Server, Hosted Chef, or AWS OpsWorks Chef Automate)
- Chef Client Credentials: A client or user account with API access
- RSA Private Key: The PEM-encoded private key for authentication
Setting Up Test Environment#
Option 1: Using Chef Manage (Chef Server Web UI)#
-
Log into Chef Manage:
-
Create or Select a Client:
- Go to Policy → Clients
- Create a new client or select an existing one
-
Download the private key (only shown once during creation)
-
Note Your Organisation:
- Check the URL or dashboard for your organisation name
- Common default is
"default"or your company name
Option 2: Using Chef Workstation CLI#
-
Install Chef Workstation:
-
Configure Knife:
-
Locate Your Credentials:
Option 3: Local Test Chef Server (Docker)#
For testing without production access, spin up a local Chef Server:
# Using Docker Compose
docker run -d \
--name chef-server \
-p 443:443 \
chef/chef-server:latest
# Access container to create client
docker exec -it chef-server bash
chef-server-ctl user-create testuser Test User test@example.com password123
chef-server-ctl org-create testorg "Test Organisation" --association_user testuser
Configuration#
Environment Variables Method (Recommended)#
Set up environment variables for testing:
# Required
export CHEF_SERVER_URL="https://your-chef-server.example.com"
export CHEF_CLIENT_NAME="your-client-name"
export CHEF_CLIENT_KEY_PATH="/path/to/client.pem"
# Optional (defaults shown)
export CHEF_ORG="default"
Direct Parameter Method#
Alternatively, pass credentials directly to tools (useful for testing different configurations):
Testing Secrets Redaction#
Test 1: Invalid Key Error (Redaction)#
Test that malformed keys are redacted in error messages:
# Create a file with invalid key content
echo "-----BEGIN RSA PRIVATE KEY-----
INVALID_KEY_CONTENT_HERE
-----END RSA PRIVATE KEY-----" > /tmp/bad-key.pem
# Run validation (should fail with redacted key)
poetry run souschef validate-chef-server \
--server-url "https://chef.example.com" \
--organisation "default" \
--client-name "testclient" \
--client-key-path "/tmp/bad-key.pem"
Expected Output:
Test 2: Authentication Failure (Redaction)#
Test that authentication errors don't leak key material:
# Use a valid key format but wrong credentials
poetry run souschef validate-chef-server \
--server-url "https://chef.example.com" \
--organisation "wrong-org" \
--client-name "wrong-client" \
--client-key-path "/path/to/valid-key.pem"
Expected Output:
Failed: Authentication failed - check your Chef Server credentials
# NOT: Any output containing the actual key content
Test 3: Connection Timeout (Safe Output)#
Test network errors don't expose credentials:
# Use unreachable server
poetry run souschef validate-chef-server \
--server-url "https://nonexistent.example.com" \
--organisation "default" \
--client-name "testclient" \
--client-key-path "/path/to/client.pem"
Expected Output:
Failed: Connection timeout - could not reach https://nonexistent.example.com
# No key material in output
CLI Testing#
Test Connection Validation#
# Test with environment variables
poetry run souschef validate-chef-server \
--server-url "$CHEF_SERVER_URL" \
--organisation "$CHEF_ORG" \
--client-name "$CHEF_CLIENT_NAME" \
--client-key-path "$CHEF_CLIENT_KEY_PATH"
Expected Success Output:
Success: Successfully connected to Chef Server at https://your-chef-server.example.com/organizations/default
Test Node Query#
# Query all nodes
poetry run souschef query-chef-nodes \
--search-query "*:*" \
--server-url "$CHEF_SERVER_URL" \
--organisation "$CHEF_ORG" \
--client-name "$CHEF_CLIENT_NAME" \
--client-key-path "$CHEF_CLIENT_KEY_PATH"
Expected Output:
{
"status": "success",
"count": 5,
"nodes": [
{
"name": "web-server-01",
"roles": ["role[webserver]"],
"environment": "production",
"platform": "ubuntu",
"ipaddress": "10.0.1.10",
"fqdn": "web-server-01.example.com"
},
...
]
}
Test with Inline Key (Not Recommended in Production)#
# Read key into variable
KEY_CONTENT=$(cat /path/to/client.pem)
# Pass inline (for testing only)
poetry run souschef validate-chef-server \
--server-url "$CHEF_SERVER_URL" \
--organisation "$CHEF_ORG" \
--client-name "$CHEF_CLIENT_NAME" \
--client-key "$KEY_CONTENT"
MCP Tool Testing#
Using Claude Desktop#
- Configure MCP Server:
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or equivalent:
{
"mcpServers": {
"souschef": {
"command": "poetry",
"args": ["run", "python", "-m", "souschef.server"],
"cwd": "/path/to/souschef",
"env": {
"CHEF_SERVER_URL": "https://your-chef-server.example.com",
"CHEF_ORG": "default",
"CHEF_CLIENT_NAME": "your-client",
"CHEF_CLIENT_KEY_PATH": "/path/to/client.pem"
}
}
}
}
- Test in Claude Desktop:
Ask Claude:
Then:
- Verify Redaction:
Intentionally break the configuration:
Restart Claude Desktop and ask it to validate the connection. The error message should show ***REDACTED*** instead of any key material.
Using MCP Inspector#
For lower-level testing:
# Install MCP Inspector
npm install -g @modelcontextprotocol/inspector
# Run with SousChef
mcp-inspector poetry run python -m souschef.server
Navigate to http://localhost:5173 and test tools interactively.
Unit Test Verification#
Run the secrets redaction test suite:
# Run all redaction tests
poetry run pytest tests/unit/test_chef_server_client.py::TestSecretsRedaction -v
# Run integration test for MCP tool redaction
poetry run pytest tests/unit/test_server.py::test_validate_chef_server_connection_redacts_keys -v
# Run all Chef Server tests
poetry run pytest tests/unit/test_chef_server_ui.py tests/unit/test_chef_server_client.py \
tests/unit/test_server.py::test_validate_chef_server_connection_success \
tests/unit/test_server.py::test_validate_chef_server_connection_redacts_keys \
tests/unit/test_server.py::test_get_chef_nodes_success -v
Debugging#
Enable Debug Logging#
To see detailed request/response information (keys still redacted):
export LOG_LEVEL=DEBUG
poetry run souschef validate-chef-server \
--server-url "$CHEF_SERVER_URL" \
--organisation "$CHEF_ORG" \
--client-name "$CHEF_CLIENT_NAME" \
--client-key-path "$CHEF_CLIENT_KEY_PATH"
Test Signature Generation#
Use Python interactively to test auth headers:
from souschef.core.chef_server import _build_auth_headers, _load_client_key
key = _load_client_key("/path/to/client.pem", None)
headers = _build_auth_headers(
"GET",
"/organizations/default/search/node?q=*:*",
b"",
"your-client-name",
"2026-02-16T12:00:00Z",
key
)
print(headers)
# Should see X-Ops-Authorization-1, X-Ops-Userid, etc.
Common Issues#
"Authentication failed" with valid credentials#
- Check organisation name: Must match Chef Server configuration
- Verify client name: Case-sensitive
- Key format: Must be unencrypted PEM format (not PKCS#8 or encrypted)
"Connection timeout"#
- Firewall: Ensure port 443 is accessible
- URL format: Include
https://scheme - DNS: Server hostname must resolve
"Client key path does not exist"#
- Path resolution: Use absolute paths, not relative
- Permissions: Key file must be readable
- Path expansion: Use
$HOMEinstead of~in environment variables
Security Considerations#
What Gets Redacted#
The _redact_sensitive_data() function redacts:
- PEM private keys: Any
-----BEGIN ... PRIVATE KEY-----blocks - Base64 key content: Multi-line base64 strings (40+ chars per line)
- Credential assignments:
password=value,token:value,secret="value"
What Doesn't Get Redacted#
Safe to include in error messages: - Server URLs - Client/user names - Organisation names - Node names, roles, environments - Status codes (401, 403, 404)
Production Recommendations#
- Use key paths: Prefer
CHEF_CLIENT_KEY_PATHoverCHEF_CLIENT_KEY - Protect key files: Set permissions to
0600 - Rotate keys: Periodically regenerate client keys
- Audit logs: Monitor Chef Server logs for API access
- Use secrets managers: Store keys in Vault, AWS Secrets Manager, etc.
Acceptance Criteria Verification#
From Issue #197, verify each criterion:
- [YES] Key-based auth: RSA signature with X-Ops-* headers
- [YES] Configuration: Server URL, org, client name via env vars
- [YES] Basic endpoints: nodes, roles, environments, cookbooks, policies
- [YES] Connection test:
validate_chef_server_connectiontool - [YES] Clear errors: HTTP status codes with helpful messages
- [YES] Secrets redaction: PEM keys and passwords masked in output
Next Steps#
After validating the integration:
- Test with production Chef Server (read-only operations first)
- Integrate with CI/CD (see docs/docker-deployment.md)
- Implement cookbook downloading (Issue #198)
- Add caching layer (reduce API calls)
Support#
If you encounter issues:
- Check the Chef Server API documentation
- Review ARCHITECTURE.md for code structure
- Open an issue on GitHub with redacted error output