# Custom Command
The `command` lease backend runs an arbitrary script or command to create (and optionally revoke) credentials. Use this for systems that fnox doesn't natively support.
## Configuration
```toml
[leases.custom]
type = "command"
create_command = "./scripts/get-creds.sh"
revoke_command = "./scripts/revoke-creds.sh" # optional
duration = "1h"
```
| `create_command` | Yes | Shell command to create credentials |
| `revoke_command` | No | Shell command to revoke credentials |
| `duration` | No | Lease duration (e.g., `"1h"`, `"30m"`) |
| `timeout` | No | Command execution timeout (default: `"30s"`) |
## Prerequisites
None — fnox can't validate prerequisites without running the command.
## Create Command
Your script receives these environment variables:
| `FNOX_LEASE_DURATION` | Requested duration in seconds |
| `FNOX_LEASE_LABEL` | Lease label (default: `fnox-lease`) |
The script must output JSON on stdout:
```json
{
"credentials": {
"MY_TOKEN": "tok-abc123",
"MY_SECRET": "sec-xyz789"
},
"expires_at": "2024-01-15T10:00:00Z",
"lease_id": "my-custom-lease-1"
}
```
| `credentials` | Yes | Key-value map of env var name to credential value |
| `expires_at` | No | Expiry timestamp (RFC3339). Omit for never-expiring leases. |
| `lease_id` | No | Unique lease ID. Auto-generated if omitted. |
## Revoke Command
If `revoke_command` is set, it's called when you run `fnox lease revoke` or `fnox lease cleanup`. It receives:
| `FNOX_LEASE_ID` | Lease ID to revoke |
## Limits
- **Max duration:** 24 hours
- **Revocation:** Only if `revoke_command` is configured
## Examples
### Basic script
```bash
#!/bin/bash
# scripts/get-creds.sh
# Call your internal API
RESPONSE=$(curl -s https://creds.internal/api/token \
--header "Authorization: Bearer $INTERNAL_AUTH" \
--data "ttl=$FNOX_LEASE_DURATION")
# Output JSON
echo "$RESPONSE"
```
### Generate JSON from CLI output with jq
Many CLIs output credentials in non-JSON formats. Use `jq` to reshape the output:
```bash
#!/bin/bash
# scripts/get-k8s-token.sh
TOKEN=$(kubectl create token my-service-account \
--duration="${FNOX_LEASE_DURATION}s" 2>/dev/null)
EXPIRY=$(date -u -d "+${FNOX_LEASE_DURATION} seconds" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
jq -n \
--arg token "$TOKEN" \
--arg exp "$EXPIRY" \
'{
credentials: { KUBE_TOKEN: $token },
expires_at: $exp
}'
```
```toml
[leases.k8s]
type = "command"
create_command = "./scripts/get-k8s-token.sh"
duration = "1h"
```
### With revocation
```bash
#!/bin/bash
# scripts/get-creds.sh
LEASE_ID="custom-$(date +%s)"
TOKEN=$(my-tool create-token --ttl "$FNOX_LEASE_DURATION")
jq -n \
--arg token "$TOKEN" \
--arg id "$LEASE_ID" \
'{
credentials: { API_TOKEN: $token },
lease_id: $id
}'
```
```bash
#!/bin/bash
# scripts/revoke-creds.sh
my-tool revoke-token "$FNOX_LEASE_ID"
```
### Wrapping `aws sts` directly
```bash
#!/bin/bash
# scripts/assume-role.sh
aws sts assume-role \
--role-arn "arn:aws:iam::123456789012:role/my-role" \
--role-session-name "$FNOX_LEASE_LABEL" \
--duration-seconds "$FNOX_LEASE_DURATION" \
| jq '{
credentials: {
AWS_ACCESS_KEY_ID: .Credentials.AccessKeyId,
AWS_SECRET_ACCESS_KEY: .Credentials.SecretAccessKey,
AWS_SESSION_TOKEN: .Credentials.SessionToken
},
expires_at: .Credentials.Expiration
}'
```
### Parsing key=value output
```bash
#!/bin/bash
# scripts/get-creds.sh
# Some tools output key=value pairs
OUTPUT=$(my-tool get-creds --format=env)
# Parse into JSON with jq
{ credentials: . }
'
```
## See Also
- [Credential Leases](/guide/leases) — overview and approaches