feat: initial release
This commit is contained in:
454
docs/detailed-guide.md
Normal file
454
docs/detailed-guide.md
Normal file
@@ -0,0 +1,454 @@
|
||||
# compliance-scan - Detailed Guide
|
||||
|
||||
Complete reference for developers and advanced users.
|
||||
|
||||
## Core Entry Points
|
||||
|
||||
| Component | Path | Purpose |
|
||||
| --------------- | ------------------------------------ | ------------------------------------- |
|
||||
| CLI | `src/sslysze_scan/__main__.py` | Command-line interface entry |
|
||||
| Scanner | `src/sslysze_scan/scanner.py` | SSLyze integration and scan execution |
|
||||
| Database Writer | `src/sslysze_scan/db/writer.py` | Scan result persistence |
|
||||
| Reporter | `src/sslysze_scan/reporter/` | Report generation (CSV/MD/reST) |
|
||||
| Compliance | `src/sslysze_scan/db/compliance.py` | BSI/IANA validation logic |
|
||||
| Query | `src/sslysze_scan/reporter/query.py` | Database queries using views |
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```bash
|
||||
# Scan server on multiple ports
|
||||
poetry run compliance-scan scan example.com:443,636
|
||||
|
||||
# Generate Markdown report
|
||||
poetry run compliance-scan report -t md -o report.md
|
||||
|
||||
# Generate CSV reports
|
||||
poetry run compliance-scan report -t csv --output-dir ./reports
|
||||
|
||||
# List all scans
|
||||
poetry run compliance-scan report --list
|
||||
```
|
||||
|
||||
## CLI Commands
|
||||
|
||||
### Scan Command
|
||||
|
||||
```
|
||||
compliance-scan scan <hostname>:<port1>,<port2> [options]
|
||||
```
|
||||
|
||||
| Argument | Required | Description |
|
||||
| -------------------- | -------- | ---------------------------------------------------------------- |
|
||||
| `<hostname>:<ports>` | Yes | Target with comma-separated ports. IPv6: `[2001:db8::1]:443,636` |
|
||||
| `--print` | No | Display summary in console |
|
||||
| `-db <path>` | No | Database file path (default: compliance_status.db) |
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
compliance-scan scan example.com:443,636 --print
|
||||
compliance-scan scan [2001:db8::1]:443,636 -db custom.db
|
||||
```
|
||||
|
||||
### Report Command
|
||||
|
||||
```
|
||||
compliance-scan report [scan_id] -t <type> [options]
|
||||
```
|
||||
|
||||
| Argument | Required | Description |
|
||||
| -------------------- | -------- | ------------------------------ |
|
||||
| `scan_id` | No | Scan ID (default: latest scan) |
|
||||
| `-t <type>` | Yes | Report type: csv, md, rest |
|
||||
| `-o <file>` | No | Output file (md/rest only) |
|
||||
| `--output-dir <dir>` | No | Output directory |
|
||||
| `--list` | No | List all available scans |
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
compliance-scan report -t md -o report.md
|
||||
compliance-scan report 5 -t csv --output-dir ./reports
|
||||
compliance-scan report -t rest --output-dir ./docs
|
||||
```
|
||||
|
||||
## Report Formats
|
||||
|
||||
### CSV
|
||||
|
||||
Generates granular files per port and category.
|
||||
|
||||
| File Pattern | Content |
|
||||
| --------------------------------------------- | -------------------------------------- |
|
||||
| `summary.csv` | Scan statistics and compliance summary |
|
||||
| `<port>_cipher_suites_<version>_accepted.csv` | Accepted cipher suites per TLS version |
|
||||
| `<port>_cipher_suites_<version>_rejected.csv` | Rejected cipher suites per TLS version |
|
||||
| `<port>_supported_groups.csv` | Elliptic curves and DH groups |
|
||||
| `<port>_missing_groups_bsi.csv` | BSI-approved groups not offered |
|
||||
| `<port>_missing_groups_iana.csv` | IANA-recommended groups not offered |
|
||||
| `<port>_certificates.csv` | Certificate chain with compliance |
|
||||
| `<port>_vulnerabilities.csv` | Vulnerability scan results |
|
||||
| `<port>_protocol_features.csv` | TLS protocol features |
|
||||
| `<port>_session_features.csv` | Session handling features |
|
||||
| `<port>_http_headers.csv` | HTTP security headers |
|
||||
| `<port>_compliance_status.csv` | Aggregated compliance per check type |
|
||||
|
||||
Behavior: Ports without TLS support generate no files. Empty sections are omitted.
|
||||
|
||||
### Markdown
|
||||
|
||||
Single comprehensive report with:
|
||||
|
||||
1. Metadata: Scan ID, hostname, IPs, timestamp, duration, ports
|
||||
2. Summary: Statistics table
|
||||
3. Per-port sections (TLS-enabled ports only):
|
||||
- TLS configuration
|
||||
- Cipher suites (accepted/rejected by version)
|
||||
- Supported groups with compliance
|
||||
- Missing groups (collapsible details)
|
||||
- Certificates with key size and compliance
|
||||
- Vulnerabilities
|
||||
- Protocol features
|
||||
- Session features
|
||||
- HTTP security headers
|
||||
|
||||
### reStructuredText
|
||||
|
||||
Identical structure to Markdown but uses `.. csv-table::` directives for Sphinx integration.
|
||||
|
||||
Use case: Generate documentation that references CSV files for tabular data.
|
||||
|
||||
## Database Structure
|
||||
|
||||
File: `compliance_status.db` (SQLite, Schema Version 5)
|
||||
|
||||
Template: `src/sslysze_scan/data/crypto_standards.db`
|
||||
|
||||
Full schema: [schema.sql](schema.sql)
|
||||
|
||||
### Scan Result Tables
|
||||
|
||||
| Table | Content |
|
||||
| ------------------------ | ------------------------------------------------------------ |
|
||||
| `scans` | Scan metadata: scan_id, hostname, ports, timestamp, duration |
|
||||
| `scanned_hosts` | Resolved FQDN with IPv4/IPv6 addresses |
|
||||
| `scan_cipher_suites` | Cipher suites per port and TLS version (accepted/rejected) |
|
||||
| `scan_supported_groups` | Elliptic curves and DH groups per port |
|
||||
| `scan_certificates` | Certificate chain with key type, size, validity |
|
||||
| `scan_vulnerabilities` | Vulnerability test results per port |
|
||||
| `scan_protocol_features` | TLS protocol features (compression, early data, etc.) |
|
||||
| `scan_session_features` | Session renegotiation and resumption |
|
||||
| `scan_http_headers` | HTTP security headers per port |
|
||||
| `scan_compliance_status` | Compliance evaluation per item and port |
|
||||
|
||||
### Database Views (Schema v5)
|
||||
|
||||
Six optimized views eliminate complex JOINs and improve query performance:
|
||||
|
||||
| View | Purpose |
|
||||
| ------------------------------------ | --------------------------------------------- |
|
||||
| `v_cipher_suites_with_compliance` | Cipher suites with BSI/IANA compliance flags |
|
||||
| `v_supported_groups_with_compliance` | Groups with compliance status |
|
||||
| `v_certificates_with_compliance` | Certificates with key size compliance |
|
||||
| `v_port_compliance_summary` | Aggregated compliance statistics per port |
|
||||
| `v_missing_bsi_groups` | BSI-approved groups not offered by server |
|
||||
| `v_missing_iana_groups` | IANA-recommended groups not offered by server |
|
||||
|
||||
### Reference Data Tables
|
||||
|
||||
IANA TLS:
|
||||
|
||||
- `iana_tls_cipher_suites`: Cipher suite registry with recommendations
|
||||
- `iana_tls_signature_schemes`: Signature algorithm registry
|
||||
- `iana_tls_supported_groups`: Named groups registry
|
||||
|
||||
BSI TR-02102-1 (Certificates):
|
||||
|
||||
- `bsi_tr_02102_1_key_requirements`: Key length requirements
|
||||
- `bsi_tr_02102_1_hash_requirements`: Hash algorithm requirements
|
||||
|
||||
BSI TR-02102-2 (TLS):
|
||||
|
||||
- `bsi_tr_02102_2_tls`: TLS cipher suites and groups with validity periods
|
||||
|
||||
BSI TR-02102-3 (IPsec/IKEv2):
|
||||
|
||||
- Encryption, integrity, DH groups
|
||||
|
||||
BSI TR-02102-4 (SSH):
|
||||
|
||||
- Key exchange, encryption, MAC
|
||||
|
||||
CSV Export Metadata:
|
||||
|
||||
- `csv_export_metadata`: Stores CSV headers as JSON for all export types
|
||||
|
||||
## Compliance Validation
|
||||
|
||||
### BSI TR-02102-1 (Certificates)
|
||||
|
||||
Key length requirements:
|
||||
|
||||
| Algorithm | Minimum Bits | Status |
|
||||
| --------- | ------------ | ----------------------------- |
|
||||
| RSA | 3000 | Required |
|
||||
| ECDSA | 250 | Required |
|
||||
| DSA | 3072 | Deprecated (valid until 2029) |
|
||||
|
||||
Hash algorithms:
|
||||
|
||||
- Allowed: SHA-256, SHA-384, SHA-512
|
||||
- Deprecated: SHA-1, MD5
|
||||
|
||||
### BSI TR-02102-2 (TLS)
|
||||
|
||||
Validates:
|
||||
|
||||
- Cipher suites against BSI-approved lists
|
||||
- Supported groups against BSI requirements
|
||||
- Validity periods (time-based expiration)
|
||||
|
||||
### IANA
|
||||
|
||||
Validates:
|
||||
|
||||
- Cipher suite recommendations (Y/N/D flags)
|
||||
- Supported group recommendations (Y/N/D flags)
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
src/sslysze_scan/
|
||||
├── __main__.py # CLI entry point
|
||||
├── cli.py # Argument parsing
|
||||
├── scanner.py # SSLyze integration
|
||||
├── protocol_loader.py # Port-protocol mapping
|
||||
├── output.py # Console output
|
||||
├── commands/
|
||||
│ ├── scan.py # Scan command handler
|
||||
│ └── report.py # Report command handler
|
||||
├── db/
|
||||
│ ├── schema.py # Schema version management
|
||||
│ ├── writer.py # Scan result storage
|
||||
│ ├── compliance.py # Compliance validation
|
||||
│ └── writers/ # Specialized writers
|
||||
├── reporter/
|
||||
│ ├── query.py # Database queries (uses views)
|
||||
│ ├── csv_export.py # CSV generation
|
||||
│ ├── markdown_export.py # Markdown generation
|
||||
│ ├── rst_export.py # reST generation
|
||||
│ └── template_utils.py # Shared utilities
|
||||
├── templates/
|
||||
│ ├── report.md.j2 # Markdown template
|
||||
│ └── report.reST.j2 # reST template
|
||||
└── data/
|
||||
├── crypto_standards.db # Template DB (IANA/BSI + schema)
|
||||
└── protocols.csv # Port-protocol mapping
|
||||
```
|
||||
|
||||
## Key Functions
|
||||
|
||||
### CLI and Parsing
|
||||
|
||||
| Function | Module | Purpose |
|
||||
| -------------------------- | -------- | ----------------------------------- |
|
||||
| `parse_host_ports(target)` | `cli.py` | Parse `hostname:port1,port2` format |
|
||||
| `parse_arguments()` | `cli.py` | Parse CLI arguments |
|
||||
|
||||
### Scanning
|
||||
|
||||
| Function | Module | Purpose |
|
||||
| ------------------------------------------------------------ | ------------ | -------------------------------- |
|
||||
| `perform_scan(hostname, port, start_time)` | `scanner.py` | Execute SSLyze scan for one port |
|
||||
| `create_scan_request(hostname, port, use_opportunistic_tls)` | `scanner.py` | Create SSLyze scan request |
|
||||
|
||||
### Database Writing
|
||||
|
||||
| Function | Module | Purpose |
|
||||
| ---------------------------------------------------------------------------- | ------------------ | --------------------------------------- |
|
||||
| `save_scan_results(db_path, hostname, ports, results, start_time, duration)` | `db/writer.py` | Store all scan results, returns scan_id |
|
||||
| `check_compliance(db_path, scan_id)` | `db/compliance.py` | Validate compliance, returns statistics |
|
||||
| `check_schema_version(db_path)` | `db/schema.py` | Verify schema compatibility |
|
||||
| `get_schema_version(db_path)` | `db/schema.py` | Get current schema version |
|
||||
|
||||
### Database Querying
|
||||
|
||||
| Function | Module | Purpose |
|
||||
| ------------------------------------- | ------------------- | ---------------------------------- |
|
||||
| `get_scan_data(db_path, scan_id)` | `reporter/query.py` | Get complete scan data using views |
|
||||
| `get_scan_metadata(db_path, scan_id)` | `reporter/query.py` | Get scan metadata only |
|
||||
| `list_scans(db_path)` | `reporter/query.py` | List all scans in database |
|
||||
|
||||
### Report Generation
|
||||
|
||||
| Function | Module | Purpose |
|
||||
| ------------------------------------------------------------ | ----------------------------- | ------------------------------------ |
|
||||
| `generate_csv_reports(db_path, scan_id, output_dir)` | `reporter/csv_export.py` | Generate all CSV files |
|
||||
| `generate_markdown_report(db_path, scan_id, output)` | `reporter/markdown_export.py` | Generate Markdown report |
|
||||
| `generate_rest_report(db_path, scan_id, output, output_dir)` | `reporter/rst_export.py` | Generate reStructuredText report |
|
||||
| `_get_headers(db_path, export_type)` | `reporter/csv_export.py` | Load CSV headers from database |
|
||||
| `build_template_context(data)` | `reporter/template_utils.py` | Prepare Jinja2 template context |
|
||||
| `generate_report_id(metadata)` | `reporter/template_utils.py` | Generate report ID (YYYYMMDD_scanid) |
|
||||
|
||||
## SQL Query Examples
|
||||
|
||||
All queries use optimized views for performance.
|
||||
|
||||
### Cipher Suites with Compliance
|
||||
|
||||
```sql
|
||||
SELECT cipher_suite_name, iana_recommended_final, bsi_approved_final, compliant
|
||||
FROM v_cipher_suites_with_compliance
|
||||
WHERE scan_id = ? AND port = ? AND accepted = 1;
|
||||
```
|
||||
|
||||
### Port Compliance Summary
|
||||
|
||||
```sql
|
||||
SELECT check_type, total, passed, percentage
|
||||
FROM v_port_compliance_summary
|
||||
WHERE scan_id = ? AND port = ?;
|
||||
```
|
||||
|
||||
### Missing BSI Groups
|
||||
|
||||
```sql
|
||||
SELECT group_name, tls_version, valid_until
|
||||
FROM v_missing_bsi_groups
|
||||
WHERE scan_id = ?;
|
||||
```
|
||||
|
||||
### Non-Compliant Certificates
|
||||
|
||||
```sql
|
||||
SELECT port, key_type, key_bits, compliant, compliance_details
|
||||
FROM v_certificates_with_compliance
|
||||
WHERE scan_id = ? AND compliant = 0;
|
||||
```
|
||||
|
||||
### Vulnerabilities
|
||||
|
||||
```sql
|
||||
SELECT port, vuln_type, vulnerable, details
|
||||
FROM scan_vulnerabilities
|
||||
WHERE scan_id = ? AND vulnerable = 1;
|
||||
```
|
||||
|
||||
## Supported Protocols
|
||||
|
||||
### Opportunistic TLS (STARTTLS)
|
||||
|
||||
| Protocol | Ports |
|
||||
| ---------- | ---------- |
|
||||
| SMTP | 25, 587 |
|
||||
| LDAP | 389 |
|
||||
| IMAP | 143 |
|
||||
| POP3 | 110 |
|
||||
| FTP | 21 |
|
||||
| XMPP | 5222, 5269 |
|
||||
| RDP | 3389 |
|
||||
| PostgreSQL | 5432 |
|
||||
|
||||
### Direct TLS
|
||||
|
||||
| Protocol | Port |
|
||||
| -------- | ---- |
|
||||
| HTTPS | 443 |
|
||||
| LDAPS | 636 |
|
||||
| SMTPS | 465 |
|
||||
| IMAPS | 993 |
|
||||
| POP3S | 995 |
|
||||
|
||||
### Not Supported
|
||||
|
||||
MySQL (proprietary TLS protocol)
|
||||
|
||||
Fallback behavior: Automatic retry with direct TLS if STARTTLS fails.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
poetry run pytest tests/ -v
|
||||
```
|
||||
|
||||
**Test structure:**
|
||||
|
||||
- `tests/conftest.py`: Fixtures with test_db, test_db_path
|
||||
- `tests/fixtures/test_scan.db`: Real scan data (Scan 1: dc.validation.lan:443,636)
|
||||
- `tests/test_csv_export.py`: 11 CSV export tests
|
||||
- `tests/test_template_utils.py`: 3 template utility tests
|
||||
- `tests/test_compliance.py`: 2 compliance tests
|
||||
- `tests/test_cli.py`: 3 CLI parsing tests
|
||||
|
||||
**Total:** 19 tests
|
||||
|
||||
**Test database setup:**
|
||||
|
||||
- Loads `crypto_standards.db` (reference data + schema)
|
||||
- Loads `test_scan.db` (scan data only)
|
||||
- Creates views dynamically
|
||||
- In-memory for speed
|
||||
|
||||
## Code Quality
|
||||
|
||||
**Linter:** Ruff
|
||||
|
||||
```bash
|
||||
poetry run ruff check src/ tests/
|
||||
poetry run ruff format src/ tests/
|
||||
```
|
||||
|
||||
**Configuration:** `pyproject.toml`
|
||||
|
||||
- Line length: 90 characters
|
||||
- Target: Python 3.13
|
||||
- Rules: PEP 8, pyflakes, isort, naming, upgrades
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.13+
|
||||
- SSLyze 6.0.0+
|
||||
- Poetry (dependency management)
|
||||
- Jinja2 3.1+
|
||||
- pytest 9.0+ (development)
|
||||
- ruff (development)
|
||||
|
||||
## Container Usage
|
||||
|
||||
```bash
|
||||
./container-build.sh
|
||||
podman run --rm compliance-scan:latest scan example.com:443
|
||||
```
|
||||
|
||||
## Database Workflow
|
||||
|
||||
1. **First scan:** Copies `crypto_standards.db` → `compliance_status.db`
|
||||
2. **Schema check:** Validates schema version (must be 5)
|
||||
3. **Scan execution:** SSLyze performs TLS analysis
|
||||
4. **Data storage:** Results written to scan tables
|
||||
5. **Compliance check:** Validation against BSI/IANA via views
|
||||
6. **Report generation:** Queries use views for optimized performance
|
||||
|
||||
## Architecture Notes
|
||||
|
||||
**Design principles:**
|
||||
|
||||
- Single database file contains everything (reference data + results)
|
||||
- Views optimize complex queries (no N+1 queries)
|
||||
- CSV headers in database (easy to modify)
|
||||
- Template-based reports (Jinja2)
|
||||
- Port-agnostic (one scan_id, multiple ports)
|
||||
|
||||
**Key decisions:**
|
||||
|
||||
- SQLite for simplicity and portability
|
||||
- Views introduced in schema v5 for performance
|
||||
- CSV export metadata centralized
|
||||
- Test fixtures use real scan data
|
||||
- Ruff for modern Python linting
|
||||
506
docs/schema.sql
Normal file
506
docs/schema.sql
Normal file
@@ -0,0 +1,506 @@
|
||||
CREATE TABLE iana_tls_cipher_suites (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
dtls TEXT,
|
||||
recommended TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_tls_signature_schemes (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
dtls TEXT,
|
||||
recommended TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_tls_supported_groups (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
dtls TEXT,
|
||||
recommended TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_tls_alerts (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
dtls TEXT,
|
||||
recommended TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_tls_content_types (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
dtls TEXT,
|
||||
recommended TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_ikev2_encryption_algorithms (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
esp TEXT,
|
||||
ikev2 TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_ikev2_prf_algorithms (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
status TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_ikev2_integrity_algorithms (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
status TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_ikev2_dh_groups (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
status TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE iana_ikev2_authentication_methods (
|
||||
value TEXT PRIMARY KEY,
|
||||
description TEXT,
|
||||
status TEXT,
|
||||
rfc_draft TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_2_tls (
|
||||
name TEXT,
|
||||
iana_number TEXT,
|
||||
category TEXT,
|
||||
tls_version TEXT,
|
||||
valid_until INTEGER,
|
||||
reference TEXT,
|
||||
notes TEXT,
|
||||
PRIMARY KEY (name, tls_version, iana_number)
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_ikev2_encryption (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
laenge TEXT,
|
||||
verwendung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_ikev2_prf (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_ikev2_integrity (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_ikev2_dh_groups (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_ikev2_auth (
|
||||
verfahren TEXT,
|
||||
bit_laenge TEXT,
|
||||
hash_funktion TEXT,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT,
|
||||
PRIMARY KEY (verfahren, hash_funktion)
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_esp_encryption (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
aes_schluessellaenge TEXT,
|
||||
verwendung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_esp_integrity (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
verwendung_bis TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_3_ah_integrity (
|
||||
verfahren TEXT PRIMARY KEY,
|
||||
iana_nr TEXT,
|
||||
spezifikation TEXT,
|
||||
verwendung_bis TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_4_ssh_kex (
|
||||
key_exchange_method TEXT PRIMARY KEY,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT,
|
||||
bemerkung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_4_ssh_encryption (
|
||||
verschluesselungsverfahren TEXT PRIMARY KEY,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT,
|
||||
bemerkung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_4_ssh_mac (
|
||||
mac_verfahren TEXT PRIMARY KEY,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_4_ssh_auth (
|
||||
signaturverfahren TEXT PRIMARY KEY,
|
||||
spezifikation TEXT,
|
||||
verwendung TEXT,
|
||||
bemerkung TEXT
|
||||
);
|
||||
CREATE INDEX idx_bsi_tls_category ON bsi_tr_02102_2_tls(category);
|
||||
CREATE INDEX idx_bsi_tls_valid_until ON bsi_tr_02102_2_tls(valid_until);
|
||||
CREATE INDEX idx_iana_cipher_recommended ON iana_tls_cipher_suites(recommended);
|
||||
CREATE INDEX idx_iana_groups_recommended ON iana_tls_supported_groups(recommended);
|
||||
CREATE TABLE bsi_tr_02102_1_key_requirements (
|
||||
algorithm_type TEXT NOT NULL,
|
||||
usage_context TEXT NOT NULL,
|
||||
min_key_length INTEGER,
|
||||
recommended_key_length INTEGER,
|
||||
valid_from INTEGER NOT NULL,
|
||||
valid_until INTEGER,
|
||||
notes TEXT,
|
||||
reference_section TEXT,
|
||||
PRIMARY KEY (algorithm_type, usage_context, valid_from)
|
||||
);
|
||||
CREATE INDEX idx_bsi_key_req_algo ON bsi_tr_02102_1_key_requirements(algorithm_type);
|
||||
CREATE INDEX idx_bsi_key_req_context ON bsi_tr_02102_1_key_requirements(usage_context);
|
||||
CREATE TABLE bsi_tr_02102_1_hash_requirements (
|
||||
algorithm TEXT PRIMARY KEY,
|
||||
min_output_bits INTEGER,
|
||||
recommended_for TEXT,
|
||||
valid_from INTEGER NOT NULL,
|
||||
deprecated INTEGER DEFAULT 0,
|
||||
notes TEXT,
|
||||
reference_section TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_1_symmetric_requirements (
|
||||
algorithm TEXT NOT NULL,
|
||||
mode TEXT,
|
||||
min_key_bits INTEGER,
|
||||
recommended_key_bits INTEGER,
|
||||
block_size_bits INTEGER,
|
||||
valid_from INTEGER NOT NULL,
|
||||
deprecated INTEGER DEFAULT 0,
|
||||
notes TEXT,
|
||||
reference_section TEXT,
|
||||
PRIMARY KEY (algorithm, mode, valid_from)
|
||||
);
|
||||
CREATE INDEX idx_bsi_sym_algo ON bsi_tr_02102_1_symmetric_requirements(algorithm);
|
||||
CREATE INDEX idx_bsi_sym_mode ON bsi_tr_02102_1_symmetric_requirements(mode);
|
||||
CREATE TABLE bsi_tr_02102_1_mac_requirements (
|
||||
algorithm TEXT PRIMARY KEY,
|
||||
min_key_bits INTEGER,
|
||||
min_tag_bits INTEGER,
|
||||
valid_from INTEGER NOT NULL,
|
||||
notes TEXT,
|
||||
reference_section TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_1_pqc_requirements (
|
||||
algorithm TEXT NOT NULL,
|
||||
parameter_set TEXT,
|
||||
usage_context TEXT NOT NULL,
|
||||
valid_from INTEGER NOT NULL,
|
||||
notes TEXT,
|
||||
reference_section TEXT,
|
||||
PRIMARY KEY (algorithm, parameter_set, usage_context)
|
||||
);
|
||||
CREATE INDEX idx_bsi_pqc_algo ON bsi_tr_02102_1_pqc_requirements(algorithm);
|
||||
CREATE INDEX idx_bsi_pqc_context ON bsi_tr_02102_1_pqc_requirements(usage_context);
|
||||
CREATE TABLE bsi_tr_02102_1_auth_requirements (
|
||||
method TEXT PRIMARY KEY,
|
||||
min_length INTEGER,
|
||||
min_entropy_bits INTEGER,
|
||||
max_attempts INTEGER,
|
||||
valid_from INTEGER NOT NULL,
|
||||
notes TEXT,
|
||||
reference_section TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_1_rng_requirements (
|
||||
class TEXT PRIMARY KEY,
|
||||
min_seed_entropy_bits INTEGER,
|
||||
valid_from INTEGER NOT NULL,
|
||||
deprecated INTEGER DEFAULT 0,
|
||||
notes TEXT,
|
||||
reference_section TEXT
|
||||
);
|
||||
CREATE TABLE bsi_tr_02102_1_metadata (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
);
|
||||
CREATE TABLE schema_version (
|
||||
version INTEGER PRIMARY KEY,
|
||||
applied_at TEXT NOT NULL,
|
||||
description TEXT
|
||||
);
|
||||
CREATE TABLE scans (
|
||||
scan_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
timestamp TEXT NOT NULL,
|
||||
hostname TEXT NOT NULL,
|
||||
ports TEXT NOT NULL,
|
||||
scan_duration_seconds REAL
|
||||
);
|
||||
CREATE TABLE sqlite_sequence(name,seq);
|
||||
CREATE TABLE scanned_hosts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
fqdn TEXT NOT NULL,
|
||||
ipv4 TEXT,
|
||||
ipv6 TEXT,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_cipher_suites (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
tls_version TEXT NOT NULL,
|
||||
cipher_suite_name TEXT NOT NULL,
|
||||
accepted BOOLEAN NOT NULL,
|
||||
iana_value TEXT,
|
||||
key_size INTEGER,
|
||||
is_anonymous BOOLEAN,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_supported_groups (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
group_name TEXT NOT NULL,
|
||||
iana_value INTEGER,
|
||||
openssl_nid INTEGER,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_certificates (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
position INTEGER NOT NULL,
|
||||
subject TEXT,
|
||||
issuer TEXT,
|
||||
serial_number TEXT,
|
||||
not_before TEXT,
|
||||
not_after TEXT,
|
||||
key_type TEXT,
|
||||
key_bits INTEGER,
|
||||
signature_algorithm TEXT,
|
||||
fingerprint_sha256 TEXT,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_vulnerabilities (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
vuln_type TEXT NOT NULL,
|
||||
vulnerable BOOLEAN NOT NULL,
|
||||
details TEXT,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_compliance_status (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
timestamp TEXT NOT NULL,
|
||||
check_type TEXT NOT NULL,
|
||||
item_name TEXT NOT NULL,
|
||||
iana_value TEXT,
|
||||
iana_recommended TEXT,
|
||||
bsi_approved BOOLEAN,
|
||||
bsi_valid_until INTEGER,
|
||||
passed BOOLEAN NOT NULL,
|
||||
severity TEXT,
|
||||
details TEXT,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_protocol_features (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
feature_type TEXT NOT NULL,
|
||||
supported BOOLEAN NOT NULL,
|
||||
details TEXT,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_session_features (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
feature_type TEXT NOT NULL,
|
||||
client_initiated BOOLEAN,
|
||||
secure BOOLEAN,
|
||||
session_id_supported BOOLEAN,
|
||||
ticket_supported BOOLEAN,
|
||||
attempted_resumptions INTEGER,
|
||||
successful_resumptions INTEGER,
|
||||
details TEXT,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE TABLE scan_http_headers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
scan_id INTEGER NOT NULL,
|
||||
port INTEGER NOT NULL,
|
||||
header_name TEXT NOT NULL,
|
||||
header_value TEXT,
|
||||
is_present BOOLEAN NOT NULL,
|
||||
FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
|
||||
);
|
||||
CREATE INDEX idx_scans_hostname ON scans(hostname);
|
||||
CREATE INDEX idx_scans_timestamp ON scans(timestamp);
|
||||
CREATE INDEX idx_scanned_hosts_scan ON scanned_hosts(scan_id);
|
||||
CREATE INDEX idx_scanned_hosts_fqdn ON scanned_hosts(fqdn);
|
||||
CREATE INDEX idx_cipher_suites_scan ON scan_cipher_suites(scan_id, port);
|
||||
CREATE INDEX idx_cipher_suites_name ON scan_cipher_suites(cipher_suite_name);
|
||||
CREATE INDEX idx_supported_groups_scan ON scan_supported_groups(scan_id);
|
||||
CREATE INDEX idx_certificates_scan ON scan_certificates(scan_id);
|
||||
CREATE INDEX idx_vulnerabilities_scan ON scan_vulnerabilities(scan_id);
|
||||
CREATE INDEX idx_compliance_scan ON scan_compliance_status(scan_id);
|
||||
CREATE INDEX idx_compliance_passed ON scan_compliance_status(passed);
|
||||
CREATE INDEX idx_protocol_features_scan ON scan_protocol_features(scan_id);
|
||||
CREATE INDEX idx_session_features_scan ON scan_session_features(scan_id);
|
||||
CREATE INDEX idx_http_headers_scan ON scan_http_headers(scan_id);
|
||||
CREATE VIEW v_cipher_suites_with_compliance AS
|
||||
SELECT
|
||||
scs.scan_id,
|
||||
scs.port,
|
||||
scs.tls_version,
|
||||
scs.cipher_suite_name,
|
||||
scs.accepted,
|
||||
scs.iana_value,
|
||||
scs.key_size,
|
||||
scs.is_anonymous,
|
||||
sc.iana_recommended,
|
||||
sc.bsi_approved,
|
||||
sc.bsi_valid_until,
|
||||
sc.passed as compliant,
|
||||
CASE
|
||||
WHEN scs.accepted = 1 THEN sc.iana_recommended
|
||||
ELSE iana.recommended
|
||||
END as iana_recommended_final,
|
||||
CASE
|
||||
WHEN scs.accepted = 1 THEN sc.bsi_approved
|
||||
ELSE (bsi.name IS NOT NULL)
|
||||
END as bsi_approved_final,
|
||||
CASE
|
||||
WHEN scs.accepted = 1 THEN sc.bsi_valid_until
|
||||
ELSE bsi.valid_until
|
||||
END as bsi_valid_until_final
|
||||
FROM scan_cipher_suites scs
|
||||
LEFT JOIN scan_compliance_status sc
|
||||
ON scs.scan_id = sc.scan_id
|
||||
AND scs.port = sc.port
|
||||
AND sc.check_type = 'cipher_suite'
|
||||
AND scs.cipher_suite_name = sc.item_name
|
||||
LEFT JOIN iana_tls_cipher_suites iana
|
||||
ON scs.cipher_suite_name = iana.description
|
||||
LEFT JOIN bsi_tr_02102_2_tls bsi
|
||||
ON scs.cipher_suite_name = bsi.name
|
||||
AND scs.tls_version = bsi.tls_version
|
||||
AND bsi.category = 'cipher_suite'
|
||||
/* v_cipher_suites_with_compliance(scan_id,port,tls_version,cipher_suite_name,accepted,iana_value,key_size,is_anonymous,iana_recommended,bsi_approved,bsi_valid_until,compliant,iana_recommended_final,bsi_approved_final,bsi_valid_until_final) */;
|
||||
CREATE VIEW v_supported_groups_with_compliance AS
|
||||
SELECT
|
||||
ssg.scan_id,
|
||||
ssg.port,
|
||||
ssg.group_name,
|
||||
ssg.iana_value,
|
||||
ssg.openssl_nid,
|
||||
sc.iana_recommended,
|
||||
sc.bsi_approved,
|
||||
sc.bsi_valid_until,
|
||||
sc.passed as compliant
|
||||
FROM scan_supported_groups ssg
|
||||
LEFT JOIN scan_compliance_status sc
|
||||
ON ssg.scan_id = sc.scan_id
|
||||
AND ssg.port = sc.port
|
||||
AND sc.check_type = 'supported_group'
|
||||
AND ssg.group_name = sc.item_name
|
||||
/* v_supported_groups_with_compliance(scan_id,port,group_name,iana_value,openssl_nid,iana_recommended,bsi_approved,bsi_valid_until,compliant) */;
|
||||
CREATE VIEW v_certificates_with_compliance AS
|
||||
SELECT
|
||||
c.scan_id,
|
||||
c.port,
|
||||
c.position,
|
||||
c.subject,
|
||||
c.issuer,
|
||||
c.serial_number,
|
||||
c.not_before,
|
||||
c.not_after,
|
||||
c.key_type,
|
||||
c.key_bits,
|
||||
c.signature_algorithm,
|
||||
c.fingerprint_sha256,
|
||||
MAX(cs.passed) as compliant,
|
||||
MAX(cs.details) as compliance_details
|
||||
FROM scan_certificates c
|
||||
LEFT JOIN scan_compliance_status cs
|
||||
ON c.scan_id = cs.scan_id
|
||||
AND c.port = cs.port
|
||||
AND cs.check_type = 'certificate'
|
||||
AND cs.item_name = (c.key_type || ' ' || c.key_bits || ' Bit')
|
||||
GROUP BY c.scan_id, c.port, c.position, c.subject, c.issuer, c.serial_number,
|
||||
c.not_before, c.not_after, c.key_type, c.key_bits,
|
||||
c.signature_algorithm, c.fingerprint_sha256
|
||||
/* v_certificates_with_compliance(scan_id,port,position,subject,issuer,serial_number,not_before,not_after,key_type,key_bits,signature_algorithm,fingerprint_sha256,compliant,compliance_details) */;
|
||||
CREATE VIEW v_port_compliance_summary AS
|
||||
SELECT
|
||||
scan_id,
|
||||
port,
|
||||
check_type,
|
||||
COUNT(*) as total,
|
||||
SUM(CASE WHEN passed = 1 THEN 1 ELSE 0 END) as passed,
|
||||
ROUND(CAST(SUM(CASE WHEN passed = 1 THEN 1 ELSE 0 END) AS REAL) / COUNT(*) * 100, 1) as percentage
|
||||
FROM scan_compliance_status
|
||||
GROUP BY scan_id, port, check_type
|
||||
/* v_port_compliance_summary(scan_id,port,check_type,total,passed,percentage) */;
|
||||
CREATE VIEW v_missing_bsi_groups AS
|
||||
SELECT
|
||||
s.scan_id,
|
||||
s.ports,
|
||||
bsi.name as group_name,
|
||||
bsi.tls_version,
|
||||
bsi.valid_until
|
||||
FROM scans s
|
||||
CROSS JOIN (
|
||||
SELECT DISTINCT name, tls_version, valid_until
|
||||
FROM bsi_tr_02102_2_tls
|
||||
WHERE category = 'dh_group'
|
||||
) bsi
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM scan_supported_groups ssg
|
||||
WHERE ssg.scan_id = s.scan_id
|
||||
AND LOWER(ssg.group_name) = LOWER(bsi.name)
|
||||
)
|
||||
/* v_missing_bsi_groups(scan_id,ports,group_name,tls_version,valid_until) */;
|
||||
CREATE VIEW v_missing_iana_groups AS
|
||||
SELECT
|
||||
s.scan_id,
|
||||
s.ports,
|
||||
iana.description as group_name,
|
||||
iana.value as iana_value
|
||||
FROM scans s
|
||||
CROSS JOIN (
|
||||
SELECT description, value
|
||||
FROM iana_tls_supported_groups
|
||||
WHERE recommended = 'Y'
|
||||
) iana
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM scan_supported_groups ssg
|
||||
WHERE ssg.scan_id = s.scan_id
|
||||
AND LOWER(ssg.group_name) = LOWER(iana.description)
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM bsi_tr_02102_2_tls bsi
|
||||
WHERE LOWER(bsi.name) = LOWER(iana.description)
|
||||
AND bsi.category = 'dh_group'
|
||||
)
|
||||
/* v_missing_iana_groups(scan_id,ports,group_name,iana_value) */;
|
||||
CREATE TABLE csv_export_metadata (
|
||||
id INTEGER PRIMARY KEY,
|
||||
export_type TEXT UNIQUE NOT NULL,
|
||||
headers TEXT NOT NULL,
|
||||
description TEXT
|
||||
);
|
||||
Reference in New Issue
Block a user