stages/oscap.autotailor: add json tailoring

With the `oscap-utils-1.3.10` release, the `autotailor` command now
supports importing a JSON tailoring file[1] that is then converted to the
XML tailoring file which is consumed by the `oscap` command in the
remediation stage.

[1] https://github.com/ComplianceAsCode/schemas/blob/main/tailoring/schema.json
This commit is contained in:
Gianluca Zuccarelli 2024-05-09 15:32:19 +01:00 committed by Gianluca Zuccarelli
parent ad265a519d
commit 4db6d4c1b4
3 changed files with 67 additions and 15 deletions

View file

@ -9,9 +9,27 @@ def main(tree, options):
# required vars
config = options["config"]
filepath = options["filepath"]
profile = config["profile_id"]
datastream = config["datastream"]
new_profile = config["new_profile"]
profile = config.get("profile_id")
new_profile = config.get("new_profile")
tailoring_file = config.get("tailoring_file")
# make sure either profile & new_profile are set
# or tailoring_filepath is set
if not ((profile and new_profile) or tailoring_file):
raise ValueError("Either profile & new profile must be set or provide filepath to json tailoring file")
if tailoring_file:
cmd = [
"/usr/bin/autotailor",
"--output", f"{tree}/{filepath.lstrip('/')}",
"--json-tailoring", f"{tree}/{tailoring_file.lstrip('/')}",
datastream,
]
subprocess.run(cmd, encoding="utf8", stdout=sys.stderr, check=True)
return 0
# tailoring rules
selected = config.get("selected", [])

View file

@ -9,17 +9,27 @@
" - requires `openscap-utils` package in the buildroot."
],
"schema": {
"additionalProperties": false,
"required": [
"filepath",
"config"
],
"properties": {
"filepath": {
"type": "string",
"description": "Filename and path to where the tailoring file will be saved"
"definitions": {
"json-tailoring": {
"additionalProperties": false,
"required": [
"datastream",
"tailoring_file"
],
"type": "object",
"description": "OpenSCAP tailoring configuration variables",
"properties": {
"datastream": {
"type": "string",
"description": "The path to the datastream file"
},
"tailoring_file": {
"type": "string",
"description": "Path to the JSON file which contains tailoring options to be imported"
}
}
},
"config": {
"tailoring": {
"additionalProperties": false,
"required": [
"profile_id",
@ -79,6 +89,27 @@
}
}
}
},
"additionalProperties": false,
"required": [
"filepath",
"config"
],
"properties": {
"filepath": {
"type": "string",
"description": "Filename and path to where the tailoring file will be saved"
},
"config": {
"oneOf": [
{
"$ref": "#/definitions/json-tailoring"
},
{
"$ref": "#/definitions/tailoring"
}
]
}
}
}
}

View file

@ -76,7 +76,8 @@ def test_oscap_autotailor_overrides_smoke(mock_subprocess_run, fake_input, stage
"value": 50,
},
]
}, "'var' is a required property"),
}, "{'profile_id': 'some-profile-id', 'datastream': 'some-datastream', 'new_profile': 'some-new-profile',"
+ " 'overrides': [{'no': 'var', 'value': 50}]} is not valid under any of the given schemas"),
({
"overrides": [
{
@ -84,7 +85,8 @@ def test_oscap_autotailor_overrides_smoke(mock_subprocess_run, fake_input, stage
"var": "some",
},
]
}, "'value' is a required property"),
}, "{'profile_id': 'some-profile-id', 'datastream': 'some-datastream', 'new_profile': 'some-new-profile',"
+ " 'overrides': [{'no': 'value', 'var': 'some'}]} is not valid under any of the given schemas"),
({
"overrides": [
{
@ -92,7 +94,8 @@ def test_oscap_autotailor_overrides_smoke(mock_subprocess_run, fake_input, stage
"value": {"some": "object"},
},
]
}, " is not of type 'string', 'integer'"),
}, "{'profile_id': 'some-profile-id', 'datastream': 'some-datastream', 'new_profile': 'some-new-profile',"
+ " 'overrides': [{'var': 'ssh_idle_timeout_value', 'value': {'some': 'object'}}]} is not valid under any of the given schemas"),
],
)
@pytest.mark.parametrize("stage_schema", ["1"], indirect=True)