Skip to content

Commit 1e3d4a6

Browse files
committed
fss: refine journal verification classification and severity handling
Signed-off-by: Julius Koskela <julius.koskela@unikie.com>
1 parent af57ec2 commit 1e3d4a6

File tree

6 files changed

+697
-306
lines changed

6 files changed

+697
-306
lines changed

docs/src/content/docs/ghaf/scs/fss.mdx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ghaf.logging.fss = {
2828
### Seal Interval Considerations
2929

3030
| Interval | Tamper Granularity | Storage Overhead | Verification Time |
31-
|----------|--------------------|------------------|-------------------|
31+
| -------- | ------------------ | ---------------- | ----------------- |
3232
| 5min | Fine | Higher (~2%) | Longer |
3333
| 15min | Moderate | Moderate (~0.5%) | Moderate |
3434
| 1h | Coarse | Lower (~0.1%) | Faster |
@@ -37,10 +37,10 @@ ghaf.logging.fss = {
3737

3838
### Key Locations
3939

40-
| Component | Sealing Key | Verification Key |
41-
|-----------|-------------|------------------|
42-
| Host | `/var/log/journal/<id>/fss` | `/persist/common/journal-fss/ghaf-host/verification-key` |
43-
| VMs | `/var/log/journal/<id>/fss` | `/etc/common/journal-fss/<vm-name>/verification-key` |
40+
| Component | Sealing Key | Verification Key |
41+
| --------- | --------------------------- | -------------------------------------------------------- |
42+
| Host | `/var/log/journal/<id>/fss` | `/persist/common/journal-fss/ghaf-host/verification-key` |
43+
| VMs | `/var/log/journal/<id>/fss` | `/etc/common/journal-fss/<vm-name>/verification-key` |
4444

4545
### Verification Key Backup
4646

@@ -55,6 +55,7 @@ cat /persist/common/journal-fss/ghaf-host/verification-key
5555
```
5656

5757
The verification key enables:
58+
5859
- Independent verification of exported journal archives
5960
- Audit by external parties without access to the live system
6061
- Disaster recovery verification
@@ -98,6 +99,7 @@ ssh root@ghaf-host /tmp/fss-test
9899
```
99100

100101
The test verifies:
102+
101103
1. FSS setup service completed
102104
2. Sealing key exists
103105
3. Verification key extracted
@@ -146,19 +148,21 @@ journalctl --verify --verify-key=<verification-key> --file=journal.export
146148

147149
### Verification Fails with "FAIL"
148150

149-
Indicates potential tampering or corruption:
151+
Indicates an integrity or corruption issue:
150152

151153
```bash
152154
# Check which files failed
153155
journalctl --verify 2>&1 | grep FAIL
154156

155157
# If only .journal~ files fail, these are temp files (not critical)
156-
# Real failures affect .journal files
158+
# If only user-*.journal or system@*.journal fail while system.journal passes,
159+
# treat this as a warning and investigate journal rotation/recovery timing.
160+
# Active system.journal failures remain critical.
157161
```
158162

159163
### "Failed to parse seed" Error
160164

161-
The verification key is malformed:
165+
The verification key is malformed or unavailable:
162166

163167
```bash
164168
# Check key format (should be ~35 bytes with '/' separator)
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#!/usr/bin/env bash
2+
# SPDX-FileCopyrightText: 2022-2026 TII (SSRC) and the Ghaf contributors
3+
# SPDX-License-Identifier: Apache-2.0
4+
# shellcheck shell=bash
5+
# shellcheck disable=SC2034
6+
7+
# Shared helpers for classifying `journalctl --verify` output.
8+
9+
fss_log_status() {
10+
local level="$1"
11+
local message="$2"
12+
local color_start=""
13+
local color_end=""
14+
15+
case "$level" in
16+
PASS)
17+
color_start="${GREEN:-}"
18+
;;
19+
FAIL)
20+
color_start="${RED:-}"
21+
;;
22+
WARN)
23+
color_start="${YELLOW:-}"
24+
;;
25+
esac
26+
27+
color_end="${NC:-}"
28+
29+
if [ -n "$color_start" ] && [ -n "$color_end" ]; then
30+
printf '%b[%s]%b %s\n' "$color_start" "$level" "$color_end" "$message"
31+
else
32+
printf '[%s] %s\n' "$level" "$message"
33+
fi
34+
}
35+
36+
fss_log_pass() {
37+
fss_log_status "PASS" "$1"
38+
}
39+
40+
fss_log_fail() {
41+
fss_log_status "FAIL" "$1"
42+
}
43+
44+
fss_log_warn() {
45+
fss_log_status "WARN" "$1"
46+
}
47+
48+
fss_log_info() {
49+
printf '[INFO] %s\n' "$1"
50+
}
51+
52+
fss_log_block() {
53+
cat
54+
}
55+
56+
fss_append_tag() {
57+
local current="$1"
58+
local tag="$2"
59+
60+
if [ -z "$current" ]; then
61+
printf '%s' "$tag"
62+
elif printf '%s\n' ",$current," | grep -Fq ",$tag,"; then
63+
printf '%s' "$current"
64+
else
65+
printf '%s,%s' "$current" "$tag"
66+
fi
67+
}
68+
69+
fss_append_line() {
70+
local current="$1"
71+
local line="$2"
72+
73+
if [ -z "$current" ]; then
74+
printf '%s' "$line"
75+
else
76+
printf '%s\n%s' "$current" "$line"
77+
fi
78+
}
79+
80+
fss_reset_classification() {
81+
FSS_REASON_TAGS=""
82+
FSS_FAIL_LINES=""
83+
FSS_TEMP_FAILURES=""
84+
FSS_ACTIVE_SYSTEM_FAILURES=""
85+
FSS_ARCHIVED_SYSTEM_FAILURES=""
86+
FSS_USER_FAILURES=""
87+
FSS_OTHER_FAILURES=""
88+
FSS_KEY_PARSE_ERROR=0
89+
FSS_KEY_REQUIRED_ERROR=0
90+
FSS_FILESYSTEM_RESTRICTION=0
91+
}
92+
93+
# shellcheck disable=SC2329
94+
fss_reason_tags_from_output() {
95+
fss_classify_verify_output "$1"
96+
printf '%s' "$FSS_REASON_TAGS"
97+
}
98+
99+
fss_classify_verify_output() {
100+
local output="$1"
101+
local line
102+
local line_lower
103+
local failure_path
104+
105+
fss_reset_classification
106+
107+
while IFS= read -r line || [ -n "$line" ]; do
108+
line_lower="${line,,}"
109+
110+
case "$line_lower" in
111+
*"bad message"*)
112+
FSS_REASON_TAGS=$(fss_append_tag "$FSS_REASON_TAGS" "BAD_MESSAGE")
113+
;;
114+
esac
115+
116+
case "$line_lower" in
117+
*"input/output error"* | *"i/o error"*)
118+
FSS_REASON_TAGS=$(fss_append_tag "$FSS_REASON_TAGS" "INPUT_OUTPUT_ERROR")
119+
;;
120+
esac
121+
122+
case "$line_lower" in
123+
*parse*seed*)
124+
FSS_REASON_TAGS=$(fss_append_tag "$FSS_REASON_TAGS" "KEY_PARSE_ERROR")
125+
FSS_KEY_PARSE_ERROR=1
126+
;;
127+
esac
128+
129+
case "$line_lower" in
130+
*"required key not available"*)
131+
FSS_REASON_TAGS=$(fss_append_tag "$FSS_REASON_TAGS" "KEY_MISSING")
132+
FSS_KEY_REQUIRED_ERROR=1
133+
;;
134+
esac
135+
136+
case "$line_lower" in
137+
*"read-only file system"* | *"permission denied"* | *"cannot create"*)
138+
FSS_REASON_TAGS=$(fss_append_tag "$FSS_REASON_TAGS" "FILESYSTEM_RESTRICTION")
139+
FSS_FILESYSTEM_RESTRICTION=1
140+
;;
141+
esac
142+
143+
case "$line" in
144+
FAIL:\ *)
145+
FSS_FAIL_LINES=$(fss_append_line "$FSS_FAIL_LINES" "$line")
146+
failure_path="${line#FAIL: }"
147+
failure_path="${failure_path%% *}"
148+
149+
case "$failure_path" in
150+
*.journal~)
151+
FSS_TEMP_FAILURES=$(fss_append_line "$FSS_TEMP_FAILURES" "$line")
152+
;;
153+
*/system.journal)
154+
FSS_ACTIVE_SYSTEM_FAILURES=$(fss_append_line "$FSS_ACTIVE_SYSTEM_FAILURES" "$line")
155+
;;
156+
*/system@*.journal)
157+
FSS_ARCHIVED_SYSTEM_FAILURES=$(fss_append_line "$FSS_ARCHIVED_SYSTEM_FAILURES" "$line")
158+
;;
159+
*/user-[0-9]*.journal)
160+
FSS_USER_FAILURES=$(fss_append_line "$FSS_USER_FAILURES" "$line")
161+
;;
162+
*)
163+
FSS_OTHER_FAILURES=$(fss_append_line "$FSS_OTHER_FAILURES" "$line")
164+
;;
165+
esac
166+
;;
167+
esac
168+
done <<<"$output"
169+
}
170+
171+
fss_classification_tags() {
172+
local tags="${1:-$FSS_REASON_TAGS}"
173+
174+
if [ -n "$FSS_ACTIVE_SYSTEM_FAILURES" ]; then
175+
tags=$(fss_append_tag "$tags" "ACTIVE_SYSTEM")
176+
fi
177+
178+
if [ -n "$FSS_ARCHIVED_SYSTEM_FAILURES" ]; then
179+
tags=$(fss_append_tag "$tags" "ARCHIVED_SYSTEM")
180+
fi
181+
182+
if [ -n "$FSS_USER_FAILURES" ]; then
183+
tags=$(fss_append_tag "$tags" "USER_JOURNAL")
184+
fi
185+
186+
if [ -n "$FSS_TEMP_FAILURES" ]; then
187+
tags=$(fss_append_tag "$tags" "TEMP")
188+
fi
189+
190+
if [ -n "$FSS_OTHER_FAILURES" ]; then
191+
tags=$(fss_append_tag "$tags" "OTHER_FAILURE")
192+
fi
193+
194+
printf '%s' "$tags"
195+
}

0 commit comments

Comments
 (0)