Skip to content

Commit 98fcba2

Browse files
committed
Add NIST 800-53 Control Viewer with gap analysis and dashboard
Add interactive web-based viewer for NIST 800-53 control files with comprehensive gap analysis, statistics dashboard, and backlog management. Features: - Dashboard view with coverage statistics and product comparison - Gap analysis showing controls without rules - Interactive filtering by family, baseline level, status, and gaps - Select All/Deselect All checkboxes for all filter categories - Full OSCAL metadata integration (description, guidance, parameters) - TODO/backlog management per control with localStorage persistence - Self-contained HTML with embedded data (works with file:// protocol) Components: - utils/nist_sync/generate_nist_viewer.py: Data generator script - utils/nist_sync/nist_viewer_template.html: Interactive HTML template - utils/nist_sync/VIEWER_README.md: Comprehensive documentation - cmake/SSGCommon.cmake: CMake macro for building viewer - .github/workflows/gh-pages.yaml: GitHub Pages integration Build with: ninja nist-viewer Published at: https://complianceascode.github.io/content-pages/nist-viewer/
1 parent 77df92b commit 98fcba2

7 files changed

Lines changed: 1926 additions & 8 deletions

File tree

.github/workflows/gh-pages.yaml

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
name: Github Pages
22
on:
33
push:
4-
branches: [ 'master' ]
4+
branches: ['master']
55
pull_request:
6-
branches: [ 'master', 'oscal-update-*' ]
6+
branches: ['master', 'oscal-update-*']
77
merge_group:
8-
branches: [ 'master' ]
8+
branches: ['master']
99
concurrency:
1010
group: ${{ github.workflow }}-${{ github.event.number || github.run_id }}
1111
cancel-in-progress: true
@@ -19,13 +19,17 @@ jobs:
1919
PAGES_DIR: __pages
2020
steps:
2121
- name: Install Deps
22-
run: dnf install -y cmake git ninja-build openscap-utils python3-pyyaml python3-jinja2 python3-pytest ansible-lint libxslt python3-pip rsync python3-lxml python3-setuptools
22+
run: |
23+
dnf install -y \
24+
cmake git ninja-build openscap-utils python3-pyyaml \
25+
python3-jinja2 python3-pytest ansible-lint libxslt \
26+
python3-pip rsync python3-lxml python3-setuptools
2327
- name: Install deps python
2428
run: pip3 install json2html prometheus_client
2529
- name: Checkout
2630
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2731
with:
28-
persist-credentials: false
32+
persist-credentials: false
2933
- name: Build
3034
run: cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug
3135
working-directory: ./build
@@ -38,8 +42,14 @@ jobs:
3842
- name: Render Policies (Using control files)
3943
run: ninja render-policies -j$(nproc)
4044
working-directory: ./build
45+
- name: Generate NIST 800-53 Control Viewer
46+
run: ninja nist-viewer
47+
working-directory: ./build
4148
- name: Generate Prometheus Metrics
42-
run: utils/controleval_metrics.py prometheus -p fedora ocp4 rhcos4 rhel10 rhel9 rhel8 sle12 sle15 -f ./build/policies_metrics
49+
run: |
50+
utils/controleval_metrics.py prometheus \
51+
-p fedora ocp4 rhcos4 rhel10 rhel9 rhel8 sle12 sle15 \
52+
-f ./build/policies_metrics
4353
env:
4454
PYTHONPATH: ${{ github.workspace }}
4555
- name: Generate HTML pages
@@ -51,8 +61,11 @@ jobs:
5161
run:
5262
git config --global --add safe.directory "$GITHUB_WORKSPACE"
5363
- name: Deploy
54-
if: ${{ github.event_name == 'push' && github.repository == 'ComplianceAsCode/content' && github.ref == 'refs/heads/master' }}
55-
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f # v4.8.0
64+
if: >-
65+
${{ github.event_name == 'push' &&
66+
github.repository == 'ComplianceAsCode/content' &&
67+
github.ref == 'refs/heads/master' }}
68+
uses: JamesIves/github-pages-deploy-action@d92aa235d04922e8f08b40ce78cc5442fcfbfa2f
5669
with:
5770
branch: main # The branch the action should deploy to.
5871
folder: ${{ env.PAGES_DIR }} # The folder the action should deploy.

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,9 @@ add_custom_target(html-profile-stats)
379379

380380
add_custom_target(render-policies)
381381

382+
# NIST 800-53 Control Viewer with Gap Analysis
383+
ssg_generate_nist_viewer()
384+
382385
ssg_build_man_page()
383386

384387
if(SSG_PRODUCT_AL2023)

cmake/SSGCommon.cmake

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,26 @@ macro(ssg_render_policies_for_product PRODUCT)
654654
)
655655
endmacro()
656656

657+
macro(ssg_generate_nist_viewer)
658+
# Generate NIST 800-53 control viewer with gap analysis
659+
# This generates for all RHEL products at once
660+
set(NIST_PRODUCTS rhel8 rhel9 rhel10)
661+
add_custom_command(
662+
OUTPUT "${CMAKE_BINARY_DIR}/nist-controls-viewer/nist-controls-viewer.html"
663+
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/nist-controls-viewer"
664+
COMMAND env "PYTHONPATH=$ENV{PYTHONPATH}" "${Python_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/utils/nist_sync/generate_nist_viewer.py"
665+
--products ${NIST_PRODUCTS}
666+
--output-dir "${CMAKE_BINARY_DIR}/nist-controls-viewer"
667+
--repo-root "${CMAKE_SOURCE_DIR}"
668+
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/nist-controls-viewer/nist-controls-viewer.html"
669+
COMMENT "[nist-viewer] generating NIST 800-53 control viewer with gap analysis"
670+
)
671+
672+
add_custom_target(nist-viewer
673+
DEPENDS "${CMAKE_BINARY_DIR}/nist-controls-viewer/nist-controls-viewer.html"
674+
)
675+
endmacro()
676+
657677
macro(ssg_make_all_tables PRODUCT)
658678
add_custom_command(
659679
OUTPUT "${CMAKE_BINARY_DIR}/tables/tables-${PRODUCT}-all.html"

utils/generate_html_pages.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,14 @@ if [ $retVal -ne 0 ]; then
112112
exit 1
113113
fi
114114

115+
# Copy NIST 800-53 Control Viewer
116+
NIST_VIEWER_DIR="$PAGES_DIR/nist-viewer"
117+
if [ -d "build/nist-controls-viewer" ]; then
118+
mkdir -p "$NIST_VIEWER_DIR"
119+
cp -rf build/nist-controls-viewer/* "$NIST_VIEWER_DIR/"
120+
echo "NIST 800-53 Control Viewer copied to $NIST_VIEWER_DIR"
121+
fi
122+
115123
# Generate Prometheus Stats
116124
PROMETHEUS_STATS_DIR="$PAGES_DIR/prometheus_stats"
117125
mkdir -p "$PROMETHEUS_STATS_DIR"
@@ -134,6 +142,7 @@ echo "<li><a href=\"guides/index.html\">Guides</a></li>" >> index.html
134142
echo "<li><a href=\"tables/index.html\">Mapping Tables</a></li>" >> index.html
135143
echo "<li><a href=\"srg_mapping/index.html\">SRG Mapping Tables</a></li>" >> index.html
136144
echo "<li><a href=\"rendered-policies/index.html\">Rendered Policies</a></li>" >> index.html
145+
echo "<li><a href=\"nist-viewer/nist-controls-viewer.html\">NIST 800-53 Control Viewer & Gap Analysis</a></li>" >> index.html
137146
echo "<li><a href=\"components/index.html\">Components</a></li>" >> index.html
138147
echo "<li><a href=\"prometheus_stats/policies_metrics\">Prometheus Policies Metrics</a></li>" >> index.html
139148
echo "</ul>" >> index.html

utils/nist_sync/VIEWER_README.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# NIST 800-53 Control Viewer & Gap Analysis
2+
3+
Interactive web-based viewer for NIST 800-53 control files with comprehensive gap analysis and backlog management features.
4+
5+
## Features
6+
7+
### Dashboard View
8+
- **Overall Coverage Statistics**: Total controls, automated, manual, and pending counts with percentages
9+
- **Gap Analysis**: Visual representation of controls without rules
10+
- **Product Comparison**: Side-by-side comparison of rhel8, rhel9, and rhel10 coverage
11+
- **Family Coverage Chart**: Bar chart showing automation coverage by control family
12+
- **Baseline Level Breakdown**: Distribution across LOW, MODERATE, and HIGH baselines
13+
- **Top Gaps List**: Quick view of controls that need rule implementation
14+
15+
### Controls View
16+
- **Advanced Filtering**:
17+
- Filter by control family (AC, AU, CM, IA, SC, SI, etc.)
18+
- Filter by baseline level (Low, Moderate, High)
19+
- Filter by status (Automated, Manual, Pending)
20+
- Filter by gap status (With Rules, Without Rules)
21+
- Full-text search across control IDs, titles, and descriptions
22+
23+
- **Control Details**:
24+
- OSCAL metadata (description, guidance, parameters)
25+
- Implementation status
26+
- Rule listings
27+
- Related controls with clickable links
28+
- Baseline level applicability
29+
30+
- **Backlog Management**:
31+
- Add TODO items per control
32+
- Mark items as complete
33+
- Delete completed items
34+
- Persistent storage in browser localStorage
35+
36+
## Building the Viewer
37+
38+
### Using CMake (Recommended)
39+
40+
```bash
41+
# Build everything including the NIST viewer
42+
cd build
43+
cmake .. -G Ninja
44+
ninja nist-viewer
45+
46+
# The viewer will be generated at:
47+
# build/nist-controls-viewer/nist-controls-viewer.html
48+
```
49+
50+
### Manual Generation
51+
52+
```bash
53+
cd utils/nist_sync
54+
55+
# Generate the viewer for specific products
56+
python3 generate_nist_viewer.py \
57+
--products rhel8 rhel9 rhel10 \
58+
--output-dir ../../build/nist-controls-viewer \
59+
--repo-root ../..
60+
61+
# Open the viewer
62+
open ../../build/nist-controls-viewer/nist-controls-viewer.html
63+
```
64+
65+
## Published Version
66+
67+
The viewer is automatically published to GitHub Pages via the `gh-pages` workflow:
68+
69+
**URL**: https://complianceascode.github.io/content-pages/nist-viewer/nist-controls-viewer.html
70+
71+
The published version updates automatically when changes are pushed to the master branch.
72+
73+
## Data Structure
74+
75+
The viewer has all control data embedded directly in the HTML file (as `EMBEDDED_DATA` JavaScript constant). This allows the viewer to work when opened directly as a local file without CORS issues.
76+
77+
A separate `nist-controls-data.json` file is also generated for reference and debugging purposes.
78+
79+
The data structure contains:
80+
81+
```json
82+
{
83+
"products": {
84+
"rhel9": {
85+
"metadata": { /* Product metadata */ },
86+
"controls": [
87+
{
88+
"id": "ac-1",
89+
"title": "Access Control Policy and Procedures",
90+
"levels": ["low", "moderate", "high"],
91+
"rules": ["rule_id_1", "rule_id_2"],
92+
"status": "automated",
93+
"description": "OSCAL description...",
94+
"guidance": "OSCAL guidance...",
95+
"parameters": [ /* ODPs */ ],
96+
"related_controls": ["ac-2", "pm-9"],
97+
"has_rules": true,
98+
"is_automated": true
99+
}
100+
]
101+
}
102+
},
103+
"statistics": {
104+
"rhel9": {
105+
"total": 1196,
106+
"automated": 850,
107+
"manual": 50,
108+
"pending": 296,
109+
"with_rules": 900,
110+
"without_rules": 296
111+
}
112+
},
113+
"families": [ /* 21 control families */ ]
114+
}
115+
```
116+
117+
## Gap Analysis Features
118+
119+
### Gap Identification
120+
Controls are marked as "gaps" when:
121+
- `status: pending` - No implementation exists
122+
- `has_rules: false` - No rules are mapped to the control
123+
124+
### Gap Visualization
125+
- **Dashboard**: Red indicator showing total gaps with percentage
126+
- **Controls List**: Red dot indicator on gap controls
127+
- **Filter**: Dedicated "Without Rules" filter to show only gaps
128+
- **Gap List**: Top 20 gaps displayed on dashboard
129+
130+
### Addressing Gaps
131+
1. Navigate to a gap control in the Controls view
132+
2. Add TODO items describing what needs to be implemented
133+
3. Create the necessary rules in the repository
134+
4. Regenerate the viewer to see updated statistics
135+
136+
## TODO/Backlog Management
137+
138+
### Adding TODOs
139+
1. Select a control
140+
2. Scroll to the "TODO / Backlog Items" section
141+
3. Type your TODO item
142+
4. Click "Add"
143+
144+
### Managing TODOs
145+
- **Check**: Mark as complete
146+
- **Uncheck**: Mark as incomplete
147+
- **Delete**: Remove the item
148+
149+
TODOs are stored in browser localStorage, so they persist across sessions but are local to your browser.
150+
151+
## Customization
152+
153+
### Modifying the Template
154+
Edit `utils/nist_sync/nist_viewer_template.html` to customize:
155+
- Styling (CSS in `<style>` section)
156+
- Layout (HTML structure)
157+
- Behavior (JavaScript functions)
158+
159+
### Adding New Statistics
160+
Modify `generate_nist_viewer.py`:
161+
1. Update `generate_viewer_data()` to calculate new statistics
162+
2. Update the template to display them
163+
164+
### Regenerate
165+
After making changes:
166+
```bash
167+
ninja nist-viewer
168+
```
169+
170+
## Workflow Integration
171+
172+
The viewer is automatically built and published by `.github/workflows/gh-pages.yaml`:
173+
174+
```yaml
175+
- name: Generate NIST 800-53 Control Viewer
176+
run: ninja nist-viewer
177+
working-directory: ./build
178+
```
179+
180+
The generated files are copied to the GitHub Pages site by `utils/generate_html_pages.sh`.
181+
182+
## Browser Compatibility
183+
184+
The viewer uses modern JavaScript features and requires:
185+
- Chrome 90+
186+
- Firefox 88+
187+
- Safari 14+
188+
- Edge 90+
189+
190+
No external dependencies - all functionality is self-contained in a single HTML file.
191+
192+
## Troubleshooting
193+
194+
### "Error loading data"
195+
- The data should be embedded in the HTML file - regenerate the viewer with `ninja nist-viewer`
196+
- If you modified the template, ensure the `/* DATA_PLACEHOLDER */` comment exists in the script section
197+
- Check browser console for specific error messages
198+
- The HTML file should be around 7MB - if it's much smaller, the data wasn't embedded properly
199+
200+
### Controls not showing
201+
- Check filter settings - try resetting all filters
202+
- Verify the data file contains controls for the selected product
203+
204+
### TODOs not persisting
205+
- localStorage must be enabled in your browser
206+
- Check browser privacy settings
207+
- TODOs are per-browser and per-domain
208+
209+
### Dashboard not rendering
210+
- Check browser console for JavaScript errors
211+
- Ensure the JSON data loaded successfully
212+
- Try refreshing the page
213+
214+
## Development
215+
216+
To develop new features:
217+
218+
1. Edit `nist_viewer_template.html`
219+
2. Test locally by opening the generated HTML file
220+
3. Regenerate after changes: `ninja nist-viewer`
221+
4. Commit both the template and updated CMake files
222+
223+
## License
224+
225+
Same license as the ComplianceAsCode/content project (BSD-3-Clause).

0 commit comments

Comments
 (0)