0
# Command-Line Interface and Utilities
1
2
Command-line script entry point and utilities for standalone STIX validation from the command line with comprehensive option support, along with exit code utilities for integration and automation.
3
4
## Capabilities
5
6
### CLI Script Entry Point
7
8
Main entry point for the `stix2_validator` command-line script that provides complete CLI interface for STIX validation.
9
10
```python { .api }
11
def main():
12
"""
13
Main entry point for the stix2_validator command-line script.
14
15
Returns:
16
None
17
18
Description:
19
Parses command line arguments, runs validation based on options,
20
prints results, and exits with appropriate status code. Handles
21
all command-line functionality including file processing, option
22
parsing, and result output.
23
24
Command-line usage:
25
stix2_validator [OPTIONS] [FILES...]
26
"""
27
```
28
29
**Example Usage:**
30
31
```bash
32
# Validate a single STIX file
33
stix2_validator threat_indicators.json
34
35
# Validate multiple files with verbose output
36
stix2_validator --verbose file1.json file2.json
37
38
# Validate directory recursively with strict checking
39
stix2_validator --recursive --strict --version 2.1 stix_files/
40
41
# Validate with custom schema directory
42
stix2_validator --schemas /path/to/schemas indicators.json
43
44
# Enable only specific validation checks
45
stix2_validator --enable 101,201,301 threat_data.json
46
47
# Disable specific validation checks
48
stix2_validator --disable 102,111 --version 2.0 legacy_data.json
49
```
50
51
**CLI Options:**
52
53
- `FILES`: Whitespace separated list of STIX files or directories to validate
54
- `--recursive, -r`: Recursively descend into input directories
55
- `--schemas, -s`: Custom schema directory for additional validation
56
- `--version`: STIX specification version to validate against ("2.0" or "2.1")
57
- `--verbose, -v`: Print informational notes and verbose error messages
58
- `--silent, -q`: Silence all output to stdout
59
- `--strict`: Treat warnings as errors and fail validation
60
- `--strict-types`: Warn if custom object types are used
61
- `--strict-properties`: Warn if custom properties are used
62
- `--enable, -e`: Comma-separated list of checks to enable
63
- `--disable, -d`: Comma-separated list of checks to disable
64
- `--enforce-refs`: Ensure referenced objects are in the same bundle
65
- `--interop`: Run validator with interoperability validation settings
66
- `--no-cache`: Disable caching of external source values
67
- `--refresh-cache`: Clear cache and download fresh external values
68
- `--clear-cache`: Clear external source cache after validation
69
70
### Exit Code Utilities
71
72
Functions and constants for processing validation results into standardized exit codes for command-line integration and automation.
73
74
```python { .api }
75
def get_code(results):
76
"""
77
Determines the exit status code from validation results.
78
79
Parameters:
80
- results (List[FileValidationResults]): List of file validation results
81
82
Returns:
83
int: Exit status code (binary OR'd combination of status flags)
84
85
Description:
86
Analyzes validation results and returns appropriate exit code.
87
Status codes are binary OR'd together to communicate multiple
88
error conditions in a single exit code.
89
"""
90
```
91
92
**Exit Status Constants:**
93
94
```python { .api }
95
EXIT_SUCCESS = 0x0 # All documents valid
96
EXIT_FAILURE = 0x1 # Fatal system error
97
EXIT_SCHEMA_INVALID = 0x2 # Schema validation failed
98
EXIT_VALIDATION_ERROR = 0x10 # Validation error occurred
99
```
100
101
**Example Usage:**
102
103
```python
104
from stix2validator import run_validation, ValidationOptions
105
from stix2validator.codes import get_code, EXIT_SUCCESS
106
107
# Configure validation options
108
options = ValidationOptions(
109
files=["threat_data.json", "indicators.json"],
110
version="2.1",
111
strict=True
112
)
113
114
# Run validation
115
results = run_validation(options)
116
117
# Get exit code based on results
118
exit_code = get_code(results)
119
120
# Handle different exit scenarios
121
if exit_code == EXIT_SUCCESS:
122
print("All validations passed successfully")
123
elif exit_code & EXIT_SCHEMA_INVALID:
124
print("Schema validation failed for one or more files")
125
# Handle schema validation failures
126
elif exit_code & EXIT_VALIDATION_ERROR:
127
print("Validation error occurred")
128
# Handle validation errors
129
elif exit_code & EXIT_FAILURE:
130
print("Fatal system error occurred")
131
# Handle system failures
132
133
# Exit with appropriate code for shell integration
134
import sys
135
sys.exit(exit_code)
136
```
137
138
### Integration Examples
139
140
#### Shell Script Integration
141
142
```bash
143
#!/bin/bash
144
145
# Validate STIX files and handle different outcomes
146
stix2_validator --version 2.1 --strict threat_intel/*.json
147
148
exit_code=$?
149
150
case $exit_code in
151
0)
152
echo "All STIX files validated successfully"
153
# Continue with processing
154
;;
155
2)
156
echo "Schema validation failed - check file format"
157
exit 1
158
;;
159
16)
160
echo "Validation error - check file accessibility"
161
exit 1
162
;;
163
*)
164
echo "Unexpected validation result: $exit_code"
165
exit 1
166
;;
167
esac
168
```
169
170
#### Python Automation Script
171
172
```python
173
import subprocess
174
import sys
175
from stix2validator.codes import EXIT_SUCCESS, EXIT_SCHEMA_INVALID, EXIT_VALIDATION_ERROR
176
177
def validate_stix_files(file_paths, version="2.1", strict=True):
178
"""
179
Validate STIX files using command-line interface.
180
181
Parameters:
182
- file_paths (List[str]): Paths to STIX files to validate
183
- version (str): STIX specification version
184
- strict (bool): Enable strict validation mode
185
186
Returns:
187
dict: Validation results summary
188
"""
189
cmd = ["stix2_validator", "--version", version]
190
191
if strict:
192
cmd.append("--strict")
193
194
cmd.extend(file_paths)
195
196
try:
197
result = subprocess.run(cmd, capture_output=True, text=True)
198
199
return {
200
"success": result.returncode == EXIT_SUCCESS,
201
"exit_code": result.returncode,
202
"stdout": result.stdout,
203
"stderr": result.stderr,
204
"schema_invalid": bool(result.returncode & EXIT_SCHEMA_INVALID),
205
"validation_error": bool(result.returncode & EXIT_VALIDATION_ERROR)
206
}
207
208
except subprocess.CalledProcessError as e:
209
return {
210
"success": False,
211
"exit_code": e.returncode,
212
"error": str(e)
213
}
214
215
# Usage example
216
files_to_validate = ["indicators.json", "malware.json", "threat_actors.json"]
217
validation_result = validate_stix_files(files_to_validate)
218
219
if validation_result["success"]:
220
print("✓ All STIX files are valid")
221
else:
222
print("✗ Validation failed:")
223
if validation_result["schema_invalid"]:
224
print(" - Schema validation errors found")
225
if validation_result["validation_error"]:
226
print(" - File access or parsing errors occurred")
227
228
print(f"Exit code: {validation_result['exit_code']}")
229
print(f"Output: {validation_result.get('stdout', '')}")
230
```
231
232
#### CI/CD Pipeline Integration
233
234
```yaml
235
# Example GitHub Actions workflow
236
name: STIX Validation
237
on: [push, pull_request]
238
239
jobs:
240
validate-stix:
241
runs-on: ubuntu-latest
242
steps:
243
- uses: actions/checkout@v2
244
245
- name: Set up Python
246
uses: actions/setup-python@v2
247
with:
248
python-version: '3.9'
249
250
- name: Install STIX Validator
251
run: pip install stix2-validator
252
253
- name: Validate STIX Files
254
run: |
255
stix2_validator --version 2.1 --strict --recursive stix_data/
256
echo "Validation exit code: $?"
257
258
- name: Validate with Custom Rules
259
run: |
260
stix2_validator --schemas custom_schemas/ --enable 1,2,3 threat_intel/
261
```
262
263
## Advanced CLI Usage
264
265
### Batch Processing Script
266
267
```python
268
#!/usr/bin/env python3
269
"""
270
Advanced STIX validation script with comprehensive reporting.
271
"""
272
273
import argparse
274
import os
275
import sys
276
from pathlib import Path
277
278
from stix2validator import run_validation, ValidationOptions
279
from stix2validator.codes import get_code, EXIT_SUCCESS
280
from stix2validator.scripts.stix2_validator import main as cli_main
281
282
def batch_validate_directory(directory, recursive=True, version="2.1"):
283
"""
284
Batch validate all STIX files in a directory with detailed reporting.
285
"""
286
options = ValidationOptions(
287
files=[directory],
288
recursive=recursive,
289
version=version,
290
verbose=True
291
)
292
293
results = run_validation(options)
294
exit_code = get_code(results)
295
296
# Generate detailed report
297
total_files = len(results)
298
valid_files = sum(1 for r in results if r.is_valid)
299
invalid_files = total_files - valid_files
300
301
print(f"\n{'='*60}")
302
print(f"STIX Validation Report")
303
print(f"{'='*60}")
304
print(f"Directory: {directory}")
305
print(f"Recursive: {recursive}")
306
print(f"STIX Version: {version}")
307
print(f"Total Files: {total_files}")
308
print(f"Valid Files: {valid_files}")
309
print(f"Invalid Files: {invalid_files}")
310
print(f"Success Rate: {(valid_files/total_files)*100:.1f}%")
311
print(f"Exit Code: {exit_code}")
312
313
if invalid_files > 0:
314
print(f"\nInvalid Files:")
315
for result in results:
316
if not result.is_valid:
317
print(f" • {result.filepath}")
318
for obj_result in result.object_results:
319
for error in obj_result.errors:
320
print(f" - {error}")
321
322
return exit_code == EXIT_SUCCESS
323
324
if __name__ == "__main__":
325
parser = argparse.ArgumentParser(description="Batch STIX validation with reporting")
326
parser.add_argument("directory", help="Directory containing STIX files")
327
parser.add_argument("--version", default="2.1", help="STIX version (2.0 or 2.1)")
328
parser.add_argument("--no-recursive", action="store_true", help="Don't recurse into subdirectories")
329
330
args = parser.parse_args()
331
332
if not os.path.isdir(args.directory):
333
print(f"Error: {args.directory} is not a valid directory")
334
sys.exit(1)
335
336
success = batch_validate_directory(
337
args.directory,
338
recursive=not args.no_recursive,
339
version=args.version
340
)
341
342
sys.exit(0 if success else 1)
343
```