kingfisher/docs/MULTI_STEP_REVOCATION.md

257 lines
7 KiB
Markdown

# Multi-Step Revocation Implementation
## Overview
This document describes the implementation of 2-step revocation support in Kingfisher. Some services require a two-step revocation process:
1. **Step 1 (Lookup)**: Query the API to retrieve an internal ID, token identifier, or other metadata
2. **Step 2 (Delete)**: Use the extracted value(s) to perform the actual revocation/deletion
## Architecture
### New Types
#### `HttpMultiStepRevocation`
```rust
pub struct HttpMultiStepRevocation {
/// Sequential steps to execute (minimum 1, maximum 2).
pub steps: Vec<RevocationStep>,
}
```
#### `RevocationStep`
```rust
pub struct RevocationStep {
/// Human-readable name for this step (e.g., "lookup_id", "delete").
pub name: Option<String>,
/// HTTP request configuration for this step.
pub request: HttpRequest,
/// Optional multipart configuration for this step.
pub multipart: Option<MultipartConfig>,
/// Variables to extract from the response for use in subsequent steps.
pub extract: Option<BTreeMap<String, ResponseExtractor>>,
}
```
#### `ResponseExtractor`
```rust
pub enum ResponseExtractor {
/// Extract from JSON response using JSONPath syntax
JsonPath { path: String },
/// Extract using regex with a capture group
Regex { pattern: String },
/// Extract an HTTP response header value
Header { name: String },
/// Use the entire response body as-is
Body,
/// Extract the HTTP status code as a string
StatusCode,
}
```
### Revocation Enum
The `Revocation` enum has been extended with:
```rust
pub enum Revocation {
AWS,
GCP,
Http(HttpValidation),
HttpMultiStep(HttpMultiStepRevocation), // New variant
}
```
## Implementation Details
### Execution Flow
1. **Validation**: Checks that 1-2 steps are defined
2. **Sequential Execution**: Each step executes in order
3. **Variable Extraction**: After each step completes, extract variables from response
4. **Variable Injection**: Extracted variables are available as Liquid templates in subsequent steps
5. **Response Validation**: Final step's `response_matcher` determines success/failure
### Key Functions
#### `extract_value_from_response()`
Extracts a value from an HTTP response based on the specified extractor type.
**Supported Extractors:**
- **JsonPath**: Basic JSONPath implementation supporting:
- Nested fields: `$.data.user.id`
- Array indexing: `$.items[0].id`
- Combined: `$.data.sessions[0].session_id`
- **Regex**: Uses first capture group from pattern match
- **Header**: Extracts value from response header by name
- **Body**: Returns entire response body
- **StatusCode**: Returns HTTP status code as string
#### `execute_revocation_step()`
Executes a single revocation step:
1. Renders URL and request templates with current variables
2. Builds and sends HTTP request
3. Extracts variables from response if configured
4. Adds extracted variables to globals for next step
#### `execute_multi_step_revocation()`
Orchestrates the multi-step revocation process:
1. Validates step count (1-2 steps)
2. Iterates through steps sequentially
3. Tracks intermediate results
4. Returns final result from last step
### Backwards Compatibility
All existing single-step revocations continue to work unchanged:
- `Revocation::AWS`
- `Revocation::GCP`
- `Revocation::Http(_)`
## Usage Examples
### Basic 2-Step Revocation
```yaml
revocation:
type: HttpMultiStep
content:
steps:
# Step 1: Get the token ID
- name: lookup_token_id
request:
method: GET
url: https://api.example.com/v1/tokens/current
headers:
Authorization: "Bearer {{ TOKEN }}"
response_matcher:
- type: StatusMatch
status: [200]
extract:
TOKEN_ID:
type: JsonPath
path: "$.data.token_id"
# Step 2: Delete the token
- name: delete_token
request:
method: DELETE
url: https://api.example.com/v1/tokens/{{ TOKEN_ID }}
headers:
Authorization: "Bearer {{ TOKEN }}"
response_matcher:
- type: StatusMatch
status: [204]
```
### Multiple Extractions
```yaml
revocation:
type: HttpMultiStep
content:
steps:
- name: get_metadata
request:
method: GET
url: https://api.service.com/tokens/info
headers:
Authorization: "Bearer {{ TOKEN }}"
response_matcher:
- type: StatusMatch
status: [200]
extract:
TOKEN_ID:
type: JsonPath
path: "$.id"
ACCOUNT_ID:
type: Header
name: X-Account-ID
TOKEN_TYPE:
type: Regex
pattern: '"type":\s*"([^"]+)"'
- name: revoke_token
request:
method: POST
url: https://api.service.com/accounts/{{ ACCOUNT_ID }}/tokens/{{ TOKEN_ID }}/revoke
headers:
Authorization: "Bearer {{ TOKEN }}"
Content-Type: application/json
body: '{"token_type":"{{ TOKEN_TYPE }}"}'
response_matcher:
- type: StatusMatch
status: [200, 204]
```
## Testing
Test your multi-step revocation using:
```bash
# Revoke a token using multi-step revocation
kingfisher revoke --rule <rule_id> <token>
# With additional variables if needed
kingfisher revoke --rule <rule_id> --var EXTRA_VAR=value <token>
```
## Files Modified
### Core Implementation
- `crates/kingfisher-rules/src/rule.rs`: Added new types and enum variants
- `crates/kingfisher-rules/src/lib.rs`: Exported new types
- `src/direct_revoke.rs`: Added multi-step execution logic
### Documentation
- `docs/RULES.md`: Added comprehensive multi-step revocation documentation
- `docs/MULTI_STEP_REVOCATION.md`: This file
### Examples
- `crates/kingfisher-rules/data/rules/example_multistep.yml`: Example rules demonstrating multi-step revocation
### Supporting Changes
- `src/reporter.rs`: Added pattern match for `HttpMultiStep` variant
## Constraints
1. **Maximum 2 steps**: The implementation supports 1-2 steps only
2. **Sequential execution**: Steps execute in order; no parallel execution
3. **Final step validation**: The last step must include `response_matcher`
4. **Variable naming**: Extracted variable names should be uppercase (convention)
5. **JSONPath limitations**: Basic implementation supporting common patterns only
## Error Handling
The implementation provides clear error messages for:
- Empty steps array
- More than 2 steps
- Missing response_matcher on final step
- Failed variable extraction
- Invalid JSONPath syntax
- Missing required headers or fields
- HTTP request failures
All errors are propagated with context about which step failed and why.
## Debug Logging
Enable debug logging to see multi-step execution details:
```bash
RUST_LOG=debug kingfisher revoke --rule <rule_id> <token>
```
Debug logs include:
- Step execution start/completion
- URLs being called
- Variables extracted and their values
- Response status codes
- Intermediate step results