# 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` ```rust pub struct RevocationStep { /// Human-readable name for this step (e.g., "lookup_id", "delete"). pub name: Option, /// HTTP request configuration for this step. pub request: HttpRequest, /// Optional multipart configuration for this step. pub multipart: Option, /// Variables to extract from the response for use in subsequent steps. pub extract: Option>, } ``` #### `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 # With additional variables if needed kingfisher revoke --rule --var EXTRA_VAR=value ``` ## 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 ``` Debug logs include: - Step execution start/completion - URLs being called - Variables extracted and their values - Response status codes - Intermediate step results