stages: add oscap-remediation stage
Add a new stage to handle openscap first boot remediation. The openscap-remediation.service looks for a `/system-update` symlink which points to an openscap config file. This stage creates both the necessary configuration and the `/system-update` symlink.
This commit is contained in:
parent
ce9253788e
commit
66d2cf6df5
1 changed files with 127 additions and 0 deletions
127
stages/org.osbuild.oscap.remediation
Executable file
127
stages/org.osbuild.oscap.remediation
Executable file
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/python3
|
||||
"""
|
||||
Execute oscap remediation on first boot
|
||||
|
||||
The OpenSCAP scanner package uses systemd's `system-update.target` to run an OpenSCAP
|
||||
remediation at first boot[1]. The `openscap-remediate.service` expects a `/system-update`
|
||||
symlink that points to an OpenSCAP offline remediation config file. The requirement
|
||||
of the config file is to have the basename of `oscap-remediate-offline.conf.sh` and
|
||||
must be accessible at boot time.
|
||||
|
||||
This stage generates the OpenSCAP offline remediation config file with the required
|
||||
configurations. A `/system-update` symlink is then created which points to the
|
||||
config file.
|
||||
|
||||
Once executed, the symlink will be removed to avoid an invocation loop. The oscap
|
||||
offline remediation configuration will be left intact.
|
||||
|
||||
[1] https://github.com/OpenSCAP/openscap/blob/maint-1.3/docs/manual/manual.adoc
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import osbuild.api
|
||||
|
||||
|
||||
SCHEMA = """
|
||||
"additionalProperties": false,
|
||||
"required": ["filename", "config"],
|
||||
"properties": {
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"description": "Filename and location where the OpenSCAP remediation config should be saved"
|
||||
},
|
||||
"config": {
|
||||
"additionalProperties": false,
|
||||
"required": ["profile_id", "datastream"],
|
||||
"type": "object",
|
||||
"description": "OpenSCAP configuration variables",
|
||||
"properties": {
|
||||
"profile_id": {
|
||||
"type": "string",
|
||||
"description": "The scap profile id"
|
||||
},
|
||||
"datastream": {
|
||||
"type": "string",
|
||||
"description": "The path to the datastream file"
|
||||
},
|
||||
"datastream_id": {
|
||||
"type": "string",
|
||||
"description": "The datastream id"
|
||||
},
|
||||
"xccdf_id": {
|
||||
"type": "string",
|
||||
"description": "The xccdf id"
|
||||
},
|
||||
"benchmark_id": {
|
||||
"type": "string",
|
||||
"description": "The benchmark id"
|
||||
},
|
||||
"tailoring": {
|
||||
"type": "string",
|
||||
"description": "The path to the custom tailoring file"
|
||||
},
|
||||
"tailoring_id": {
|
||||
"type": "string",
|
||||
"description": "The tailoring id"
|
||||
},
|
||||
"arf_result": {
|
||||
"type": "string",
|
||||
"description": "Filename and path for saving the arf results"
|
||||
},
|
||||
"html_report": {
|
||||
"type": "string",
|
||||
"description": "Filename and path for saving the html report"
|
||||
},
|
||||
"verbose_log": {
|
||||
"type": "string",
|
||||
"description": "Filename and path for verbose error messages"
|
||||
},
|
||||
"verbose_level": {
|
||||
"type": "string",
|
||||
"enum": ["DEVEL", "INFO", "ERROR", "WARNING"],
|
||||
"description": "The verbosity level for the log messages"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
# Map containing the translations between
|
||||
# our configuration names and the OpenScap
|
||||
# configuration names.
|
||||
OSCAP_OPTIONS = {
|
||||
"datastream" : "OSCAP_REMEDIATE_DS",
|
||||
"profile_id" : "OSCAP_REMEDIATE_PROFILE_ID",
|
||||
"datastream_id" : "OSCAP_REMEDIATE_DATASTREAM_ID",
|
||||
"xccdf_id" : "OSCAP_REMEDIATE_XCCDF_ID",
|
||||
"benchmark_id" : "OSCAP_REMEDIATE_BENCHMARK_ID",
|
||||
"tailoring" : "OSCAP_REMEDIATE_TAILORING",
|
||||
"tailoring_id" : "OSCAP_REMEDIATE_TAILORING_ID",
|
||||
"arf_result" : "OSCAP_REMEDIATE_ARF_RESULT",
|
||||
"html_report" : "OSCAP_REMEDIATE_HTML_REPORT",
|
||||
"verbose_log" : "OSCAP_REMEDIATE_VERBOSE_LOG",
|
||||
"verbose_level" : "OSCAP_REMEDIATE_VERBOSE_LEVEL",
|
||||
}
|
||||
|
||||
def main(tree, options):
|
||||
filename = options["filename"]
|
||||
config = options["config"]
|
||||
|
||||
with open(f"{tree}/{filename}", "w", encoding="utf-8") as f:
|
||||
for ours, theirs in OSCAP_OPTIONS.items():
|
||||
value = config.get(ours)
|
||||
if value:
|
||||
f.write(f"{theirs}={value}\n")
|
||||
|
||||
os.symlink(f"{filename}", f"{tree}/system-update")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = osbuild.api.arguments()
|
||||
r = main(args["tree"], args["options"])
|
||||
sys.exit(r)
|
||||
Loading…
Add table
Add a link
Reference in a new issue