mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 13:51:36 +00:00
feat(M40): F5 BIG-IP target connector via iControl REST
Replace 190-line stub with full iControl REST implementation (~580 lines). Token auth with 401 auto-retry, file upload + crypto object install, transaction-based atomic SSL profile updates, cleanup on failure. Injectable F5Client interface for cross-platform testing. 32 tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -92,7 +92,7 @@ flowchart TB
|
||||
T7["Caddy\n(admin API / file)"]
|
||||
T8["Envoy\n(file-based SDS)"]
|
||||
T9["Postfix/Dovecot\n(file + service reload)"]
|
||||
T2["F5 BIG-IP\n(proxy agent + iControl REST, planned)"]
|
||||
T2["F5 BIG-IP\n(proxy agent + iControl REST)"]
|
||||
T3["IIS\n(WinRM + local)"]
|
||||
end
|
||||
|
||||
@@ -418,7 +418,7 @@ The agent deploys certificates using target connectors. Each connector knows how
|
||||
- **NGINX**: Writes cert/chain/key files to disk, validates config with `nginx -t`, reloads with `nginx -s reload` or `systemctl reload nginx`
|
||||
- **Apache httpd**: Writes separate cert/chain/key files, validates with `apachectl configtest`, graceful reload
|
||||
- **HAProxy**: Builds a combined PEM file (cert + chain + key), optionally validates config, reloads via systemctl or signal
|
||||
- **F5 BIG-IP** (planned): A proxy agent in the same network zone calls the iControl REST API to upload certificate and update SSL profile bindings. The server assigns the work; the proxy agent executes it.
|
||||
- **F5 BIG-IP**: A proxy agent in the same network zone calls the iControl REST API to upload certificate/key files, install crypto objects, and update the SSL client profile within an atomic transaction. The server assigns the work; the proxy agent executes it.
|
||||
- **IIS** (implemented, dual-mode): (1) Agent-local (recommended) — a Windows agent on the IIS box runs PowerShell `Import-PfxCertificate` + `Set-WebBinding` directly with PFX conversion and SHA-1 thumbprint computation. (2) Proxy agent WinRM — for agentless IIS targets, a nearby Windows agent reaches the IIS box via WinRM.
|
||||
|
||||
The agent handles both the certificate (public) and the private key (read from local key store at `CERTCTL_KEY_DIR`). The control plane never sees the private key and never initiates outbound connections to agents or targets (pull-only model).
|
||||
@@ -528,7 +528,7 @@ flowchart TB
|
||||
TI --> EV["Envoy"]
|
||||
TI --> PO["Postfix/Dovecot"]
|
||||
TI --> IIS["IIS"]
|
||||
TI --> F5["F5 BIG-IP (interface only)"]
|
||||
TI --> F5["F5 BIG-IP"]
|
||||
end
|
||||
|
||||
subgraph "Notifier Connectors"
|
||||
|
||||
+19
-6
@@ -704,24 +704,37 @@ All commands are validated against shell injection via `validation.ValidateShell
|
||||
|
||||
Location: `internal/connector/target/postfix/postfix.go`
|
||||
|
||||
### F5 BIG-IP (Interface Only)
|
||||
### F5 BIG-IP (Implemented)
|
||||
|
||||
The F5 BIG-IP target connector interface is defined with the iControl REST flow mapped out, but the actual API calls are not yet implemented. F5 appliances can't run agents directly, so this connector uses the **proxy agent pattern**: a designated agent in the same network zone picks up F5 deployment jobs and calls the iControl REST API. The server assigns the work; the proxy agent executes it.
|
||||
The F5 BIG-IP target connector deploys certificates to F5 load balancers via the iControl REST API. F5 appliances can't run agents directly, so this connector uses the **proxy agent pattern**: a designated certctl agent in the same network zone polls for F5 deployment jobs and executes iControl REST calls on behalf of the control plane. Minimum supported BIG-IP version: 12.0+.
|
||||
|
||||
The planned flow is: authenticate via `POST /mgmt/shared/authn/login`, upload cert PEM via `POST /mgmt/tm/ltm/certificate`, update the SSL profile via `PATCH /mgmt/tm/ltm/profile/client-ssl/{profile}`, and validate deployment by checking profile status.
|
||||
The deployment flow uses F5's transaction API for atomic updates: authenticate via token auth, upload cert/key/chain PEM files, install as crypto objects, update the SSL client profile within a transaction, and commit. If the transaction fails, F5 rolls back automatically and the connector cleans up uploaded crypto objects. Updating an SSL profile automatically takes effect on all bound virtual servers — no separate virtual server binding step is needed.
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `host` | string | *(required)* | F5 BIG-IP management hostname or IP |
|
||||
| `port` | int | `443` | iControl REST API port |
|
||||
| `username` | string | *(required)* | Administrative username |
|
||||
| `password` | string | *(required)* | Administrative password |
|
||||
| `partition` | string | `Common` | F5 partition for crypto objects and profiles |
|
||||
| `ssl_profile` | string | *(required)* | SSL client profile name to update |
|
||||
| `insecure` | bool | `true` | Skip TLS verification for management interface (self-signed certs common) |
|
||||
| `timeout` | int | `30` | HTTP timeout in seconds |
|
||||
|
||||
Configuration (defined, not yet functional):
|
||||
```json
|
||||
{
|
||||
"host": "f5.internal.example.com",
|
||||
"port": 443,
|
||||
"username": "admin",
|
||||
"password": "...",
|
||||
"partition": "Common",
|
||||
"ssl_profile": "/Common/clientssl_api"
|
||||
"ssl_profile": "clientssl_api",
|
||||
"insecure": true,
|
||||
"timeout": 30
|
||||
}
|
||||
```
|
||||
|
||||
Note: F5 credentials are stored on the proxy agent, not on the control plane server. This limits the credential blast radius to the proxy agent's network zone.
|
||||
F5 credentials are stored on the proxy agent, not on the control plane server. This limits the credential blast radius to the proxy agent's network zone. Config fields are validated against regex patterns to prevent injection.
|
||||
|
||||
Location: `internal/connector/target/f5/f5.go`
|
||||
|
||||
|
||||
+72
-3
@@ -6453,15 +6453,84 @@ These must be green before starting manual QA:
|
||||
|
||||
**PASS if** CA cert PEM returned successfully.
|
||||
|
||||
### Part 45: F5 BIG-IP Target Connector (M40)
|
||||
|
||||
**Prerequisites:** F5 BIG-IP device (v12.0+) with iControl REST enabled, admin credentials, SSL client profile configured, proxy agent in same network zone.
|
||||
|
||||
#### Automated Tests
|
||||
|
||||
| Test | Description | Method | Pass? | Date | Notes |
|
||||
|------|-------------|--------|-------|------|-------|
|
||||
| 45.s1 | `TargetTypeF5` constant exists in domain | Auto | ☐ | | `grep 'TargetTypeF5' internal/domain/connector.go` |
|
||||
| 45.s2 | F5 connector tests pass | Auto | ☐ | | `go test ./internal/connector/target/f5/... -v` |
|
||||
| 45.s3 | F5 config fields in TargetsPage.tsx | Auto | ☐ | | `grep 'ssl_profile' web/src/pages/TargetsPage.tsx` |
|
||||
| 45.s4 | F5 in OpenAPI TargetType enum | Auto | ☐ | | `grep 'F5' api/openapi.yaml` |
|
||||
| 45.s5 | Agent dispatch handles F5 error return | Auto | ☐ | | `grep 'f5.New' cmd/agent/main.go` |
|
||||
| 45.s6 | F5 connector docs updated (not "Interface Only") | Auto | ☐ | | `grep 'Implemented' docs/connectors.md` |
|
||||
| 45.s7 | Frontend build succeeds | Auto | ☐ | | `cd web && npm run build` |
|
||||
| 45.s8 | Full Go build succeeds | Auto | ☐ | | `go build ./cmd/server/... ./cmd/agent/... ./cmd/cli/... ./cmd/mcp-server/...` |
|
||||
|
||||
#### Manual Tests
|
||||
|
||||
**45.M1: Validate F5 Connectivity**
|
||||
|
||||
1. Configure proxy agent with F5 target (host, username, password, partition, ssl_profile)
|
||||
2. Trigger ValidateConfig — verify authentication succeeds
|
||||
3. Verify log line: `F5 configuration validated`
|
||||
|
||||
**PASS if** auth token obtained, no errors.
|
||||
|
||||
**45.M2: Deploy Certificate to F5**
|
||||
|
||||
1. Create certificate, assign to F5 target via proxy agent
|
||||
2. Trigger deployment — verify full iControl REST flow (upload → install → transaction → profile update → commit)
|
||||
3. Verify SSL profile updated via F5 management GUI or `GET /mgmt/tm/ltm/profile/client-ssl/~Common~{profile}`
|
||||
4. Verify virtual servers bound to the profile serve the new cert
|
||||
|
||||
**PASS if** certificate deployed, profile updated, virtual servers serving new cert.
|
||||
|
||||
**45.M3: Deploy Without Chain**
|
||||
|
||||
1. Issue a cert without chain (self-signed or single-issuer)
|
||||
2. Deploy to F5 — verify chain upload/install steps are skipped
|
||||
3. Verify profile updated with cert and key only (no chain field)
|
||||
|
||||
**PASS if** deployment succeeds without chain, profile has cert/key but no chain.
|
||||
|
||||
**45.M4: Transaction Rollback on Failure**
|
||||
|
||||
1. Configure an invalid SSL profile name
|
||||
2. Trigger deployment — verify upload/install succeeds but profile update fails
|
||||
3. Verify transaction rolled back (F5 auto-rollback)
|
||||
4. Verify cleanup: uploaded crypto objects deleted from F5
|
||||
|
||||
**PASS if** error reported, crypto objects cleaned up.
|
||||
|
||||
**45.M5: Validate Deployment**
|
||||
|
||||
1. After successful deployment, call ValidateDeployment
|
||||
2. Verify SSL profile queried and cert name returned in metadata
|
||||
3. Verify `current_cert` metadata matches the deployed cert object name
|
||||
|
||||
**PASS if** validation returns Valid=true with correct cert reference.
|
||||
|
||||
**45.M6: Token Refresh on 401**
|
||||
|
||||
1. Deploy with valid credentials
|
||||
2. Wait for token to expire (or manually invalidate)
|
||||
3. Trigger another deployment — verify automatic re-authentication and retry
|
||||
|
||||
**PASS if** deployment succeeds after token refresh.
|
||||
|
||||
### Summary
|
||||
|
||||
| Category | Count |
|
||||
|----------|-------|
|
||||
| ☑ Auto (passed in `qa-smoke-test.sh`) | 144 |
|
||||
| ☐ Auto (not yet run) | 28 |
|
||||
| ☐ Auto (not yet run) | 36 |
|
||||
| — Skipped (preconditions not met in demo) | 5 |
|
||||
| ☐ Manual (requires hands-on verification) | 253 |
|
||||
| **Total** | **430** |
|
||||
| ☐ Manual (requires hands-on verification) | 259 |
|
||||
| **Total** | **444** |
|
||||
|
||||
**Automated tests must also be green.** CI passing is necessary but not sufficient — this manual QA catches integration issues that isolated unit tests miss.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user