DetectionsDetection as CodeTest/Upload Detections

Test/Upload Detections

When it’s time to upload detections, RunReveal’s CLI provides comprehensive testing and validation tools to ensure your detections are properly formatted and error-free before deployment. This guide walks you through the complete workflow from validation to deployment.

Learn more about CI/CD for detections: Check out our guide on Building a CI/CD Pipeline for RunReveal Detections to learn how to implement automated testing and deployment workflows for your detection-as-code setup.

Validate your detection syntax with lint

Before uploading, validate your detection files for syntax errors and best practices using the lint command. This step catches common issues early and ensures your detections will deploy successfully.

Basic lint syntax

# Lint Sigma detections
runreveal lint sigma <file-or-directory>
 
# Lint SQL detections  
runreveal lint sql <file-or-directory>

Lint Sigma detections

Validate Sigma rule files for proper YAML syntax and Sigma specification compliance:

# Lint a single Sigma file
runreveal lint sigma ~/detection-as-code/1password/1password-unusual-client.yaml
 
# Lint all Sigma files in a directory
runreveal lint sigma ~/detection-as-code/sigma/
 
# Lint multiple directories
runreveal lint sigma ~/detection-as-code/1password/ ~/detection-as-code/cf-audit/

Lint SQL detections

Format and validate SQL detection files using ClickHouse standards:

# Lint a single SQL file
runreveal lint sql ~/detection-as-code/sql/privilege-escalation.sql
 
# Lint all SQL files in a directory
runreveal lint sql ~/detection-as-code/sql/
 
# Lint multiple directories
runreveal lint sql ~/detection-as-code/sql/ ~/detection-as-code/custom-sql/

Lint output examples

Successful lint (no errors):

$ runreveal lint sigma ~/detection-as-code/1password/1password-unusual-client.yaml
 All Sigma files passed validation

Failed lint (with errors):

$ runreveal lint sigma ~/detection-as-code/invalid-rule.yaml
 Validation failed for invalid-rule.yaml:
   - Missing required field: 'title'
   - Invalid YAML syntax at line 5

Test your upload

Before uploading your detections, you should test them to ensure they work correctly. RunReveal CLI provides testing capabilities for both SQL and Sigma detections.

Testing SQL Detections

SQL detections are tested against actual data in your workspace. The test command executes your query against real log data to verify it returns expected results.

  1. Test a SQL detection:

    runreveal detections test --file my-detection.yaml --from "now-1h" --to "now"

    The --from and --to parameters specify the time range to query. Use relative times like "now-1h" or absolute times like "2024-01-01T00:00:00Z".

  2. Example SQL detection test:

    $ runreveal detections test --file root_account_usage.yaml --from "now-24h" --to "now"
     Query executed successfully
     Returned 3 results
  3. Verify results match expectations: Review the returned results to ensure your detection is matching the correct events and returning the expected fields.

Testing Sigma Detections

Sigma detections can be tested against local sample event files without requiring workspace data. This allows you to test your detection logic before deploying.

  1. Create a sample events file: Create a file in NDJSON format (one JSON object per line, no commas between lines, no array brackets):

    {"eventName": "suspicious_login", "user": "test-user", "srcIP": "192.168.1.100", "severity": "high", "timestamp": "2024-01-01T12:00:00Z"}
    {"eventName": "suspicious_login", "user": "test-user-2", "srcIP": "192.168.1.100", "severity": "high", "timestamp": "2024-01-01T12:01:00Z"}
    {"eventName": "normal_login", "user": "admin", "srcIP": "10.0.0.1", "severity": "low", "timestamp": "2024-01-01T12:02:00Z"}

    Save this as sample-events.ndjson. You can copy events from the RunReveal dashboard or create test events that match your detection logic.

  2. Test the Sigma detection:

    runreveal detections run --file my-sigma-detection.yaml --input sample-events.ndjson
  3. Review test output: The command shows which events in your sample file would trigger the detection:

    line 1 matches detection My Sigma Detection
    line 2 matches detection My Sigma Detection
    line 3 does not match detection My Sigma Detection

Best Practices for Testing

  1. Test with both positive and negative cases: Include events that should match your detection and events that should not match to verify your logic is correct.

  2. Test edge cases: Include events with missing fields, null values, or unexpected data formats to ensure your detection handles them gracefully.

  3. Use realistic test data: For SQL detections, test against actual production-like data. For Sigma detections, use sample events that closely match your real log structure.

  4. Test before deploying: Always test your detections locally before uploading them to your workspace to catch issues early.

For complete CLI command reference, see Using the CLI - Detections Test.

Dry run preview

When you want to see which detections have been updated, deleted, or created without actually uploading them, use the dry run flag:

$ runreveal detections sync -d ~/detection-as-code --dry-run                                                            
processing '/Users/evan/detection-as-code/1password/1password-unusual-client.yaml'                                           
processing '/Users/evan/detection-as-code/cf-audit/anomalous-api-key-usage.yaml'                                             
processing '/Users/evan/detection-as-code/cf-audit/new-cloudflare-api-key.yaml'                                              
processing '/Users/evan/detection-as-code/cf-audit/user-added-removed-cloudflare.yaml
...
{                                                                                                                            
     "detections": {                                                                                                         
         "added": [                                                                                                                                                                                                                                       
             "1password-unusual-client",                                                                                                                                                                                                             
             "anomalous-api-key-usage",                                                                                                                                                                                                                 
             "new-cloudflare-api-key",                                                                                                                                                                                                                        
         ],
         "deleted": [],                                                                                                                                                                                                                                   
         "updated": [                                                                                                                                                                                                                                     
             "user-added-removed-cloudflare"                                                                                         
         ]                                                                                                                   
     },                                                                                                                      
     "dryRun": true                                                                                                          
 }                          

Uploading

The only difference between uploading and performing a dryrun is the --dry-run flag. Remove the --dry-run flag and your detections will be uploaded.

$ runreveal detections sync -d ~/detection-as-code

If you created a detection in the UI, and then attempt to upload your detection from the CLI you will see an error message the first time you attempt to overwrite your UI detection.

It will look a little something like this:

$ runreveal detections sync -d ~/detection-as-code --dry-run                                                            
processing '/Users/evan/detection-as-code/1password/1password-unusual-client.yaml'                                           
processing '/Users/evan/detection-as-code/cf-audit/anomalous-api-key-usage.yaml'                                             
processing '/Users/evan/detection-as-code/cf-audit/new-cloudflare-api-key.yaml'                                              
processing '/Users/evan/detection-as-code/cf-audit/user-added-removed-cloudflare.yaml
ERROR  This detection name is already in use, please choose a different name. If you're trying to upload your detections using detection as code, try the -o flag to overwrite existing detections created in the UI.

If you see this error, then adding the -o flag will overwrite the existing detection and convert the detection from being web managed to being cli managed.

Force uploading with overwrite

If you receive an error because the detections are managed with the web interface, you’ll need to run the following command to convert your detections to managed by the CLI:

runreveal detections sync -o -d ~/detection-as-code
  1. Lint your detections - Validate syntax and format
  2. Dry run - Preview changes without deployment
  3. Upload - Deploy validated detections
  4. Monitor - Check for any runtime issues

This workflow ensures your detections are properly validated before reaching production.

Now that you understand testing and uploading detections, explore these related guides: