gitlab-compliance 2.5.0__tar.gz → 2.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/PKG-INFO +8 -8
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/pyproject.toml +14 -12
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/environment.py +7 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/steps/given_steps.py +19 -0
- gitlab_compliance-2.7.0/src/compliance/builtin_policies/baseline-jobs.feature +45 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/component-inputs.feature +18 -1
- gitlab_compliance-2.7.0/src/compliance/builtin_policies/include-pinning.feature +46 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-ci-conventions.feature +22 -4
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-command-substitution.feature +15 -3
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-conditionals.feature +15 -3
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-error-handling.feature +21 -4
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-file-operations.feature +20 -4
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-pinning.feature +77 -11
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-pipelines.feature +15 -3
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-portability.feature +23 -4
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-quoting.feature +26 -5
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-references.feature +12 -2
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/shell/shell-security.feature +39 -6
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/supply-chain/image-pinning.feature +36 -5
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/supply-chain/include-versions.feature +58 -7
- gitlab_compliance-2.7.0/src/compliance/builtin_policies/supply-chain/service-pinning.feature +30 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/variable-allowlist.feature +13 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/console.py +6 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/include_fetch.py +6 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/include_resolution.py +4 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/metadata.py +12 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/model.py +39 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/models.py +2 -0
- gitlab_compliance-2.7.0/src/compliance/policy_doc.py +341 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/policy_fix.py +12 -12
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/render.py +69 -15
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/runner.py +820 -811
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/script_analysis.py +2 -2
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/shell_lex.py +2 -2
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/shell_render.py +42 -8
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/gitlab_compliance.py +148 -6
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/gitstrings.py +7 -4
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/pipeline_data.py +539 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/swagger_markdown.py +3 -1
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/table_render.py +2 -1
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/yaml_paths.py +2 -1
- gitlab_compliance-2.5.0/src/compliance/builtin_policies/baseline-jobs.feature +0 -17
- gitlab_compliance-2.5.0/src/compliance/builtin_policies/include-pinning.feature +0 -15
- gitlab_compliance-2.5.0/src/compliance/builtin_policies/supply-chain/service-pinning.feature +0 -7
- gitlab_compliance-2.5.0/src/compliance/policy_doc.py +0 -183
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/LICENSE +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/docs/index.md +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/__init__.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/__init__.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/api_config.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/api_enrichment.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/steps/__init__.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/steps/script_steps.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/steps/then_steps.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/steps/when_steps.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/builtin_policies/__init__.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/container_fix.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/gitlab_api.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/image_versions.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/include_fix.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/include_versions.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/merge_requests.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/oci_registry.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/release_cache.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/secret_redact.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/stash.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/supply_chain_fix.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/gitlab_docs.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/__init__.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/command_reference.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/common.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/constants.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/doc_controller.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/gitlab_reference.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/job_composition.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/logging.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/output_filters.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/release.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/swagger_html.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/yaml_lines.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/modules/yaml_md_table.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/__init__.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/extract_job_attribute.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/includes.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/inputs.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/jobs.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/variables.py +0 -0
- {gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/properties/workflows.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-compliance
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
4
4
|
Summary: BDD compliance testing for GitLab CI/CD pipelines and project settings — by MaturityBuilder
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -19,22 +19,22 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
20
20
|
Classifier: Topic :: Software Development :: Testing
|
|
21
21
|
Requires-Dist: behave (>=1.2.6,<2.0.0)
|
|
22
|
-
Requires-Dist: click (>=8.
|
|
23
|
-
Requires-Dist: idna (==3.
|
|
22
|
+
Requires-Dist: click (>=8.5.0,<9.0.0)
|
|
23
|
+
Requires-Dist: idna (==3.20)
|
|
24
24
|
Requires-Dist: jq (==1.12.0)
|
|
25
25
|
Requires-Dist: loguru (==0.7.2)
|
|
26
26
|
Requires-Dist: markdown-analysis (==0.1.5)
|
|
27
|
-
Requires-Dist: oras (==0.2.
|
|
27
|
+
Requires-Dist: oras (==0.2.43)
|
|
28
28
|
Requires-Dist: oyaml
|
|
29
29
|
Requires-Dist: prettytable
|
|
30
30
|
Requires-Dist: pytablewriter (==1.2.1)
|
|
31
|
-
Requires-Dist: python-gitlab (==8.
|
|
31
|
+
Requires-Dist: python-gitlab (==8.6.0)
|
|
32
32
|
Requires-Dist: pyyaml (==6.0.3)
|
|
33
33
|
Requires-Dist: requests (==2.34.2)
|
|
34
34
|
Requires-Dist: rich (==15.0.0)
|
|
35
|
-
Requires-Dist: semver (==3.0
|
|
36
|
-
Requires-Dist: typer (==0.27.
|
|
37
|
-
Requires-Dist: urllib3 (==2.
|
|
35
|
+
Requires-Dist: semver (==3.1.0)
|
|
36
|
+
Requires-Dist: typer (==0.27.2)
|
|
37
|
+
Requires-Dist: urllib3 (==2.8.0)
|
|
38
38
|
Project-URL: Documentation, https://maturitybuilder.github.io/gitlab-compliance/
|
|
39
39
|
Project-URL: Home Page, https://maturitybuilder.github.io/gitlab-compliance/
|
|
40
40
|
Project-URL: Repository, https://github.com/MaturityBuilder/gitlab-compliance
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "gitlab-compliance"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.7.0"
|
|
4
4
|
dynamic = [ "readme" ]
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -40,18 +40,18 @@ python = ">=3.12"
|
|
|
40
40
|
prettytable = "*"
|
|
41
41
|
pytablewriter = "1.2.1"
|
|
42
42
|
oyaml = "*"
|
|
43
|
-
typer = "0.27.
|
|
43
|
+
typer = "0.27.2"
|
|
44
44
|
markdown-analysis = "0.1.5"
|
|
45
|
-
urllib3 = "2.
|
|
45
|
+
urllib3 = "2.8.0"
|
|
46
46
|
jq = "1.12.0"
|
|
47
|
-
click = "^8.
|
|
48
|
-
semver = "3.0
|
|
47
|
+
click = "^8.5.0"
|
|
48
|
+
semver = "3.1.0"
|
|
49
49
|
pyyaml = "6.0.3"
|
|
50
50
|
loguru = "0.7.2"
|
|
51
|
-
python-gitlab = "8.
|
|
51
|
+
python-gitlab = "8.6.0"
|
|
52
52
|
rich = "15.0.0"
|
|
53
|
-
oras = "0.2.
|
|
54
|
-
idna = "3.
|
|
53
|
+
oras = "0.2.43"
|
|
54
|
+
idna = "3.20"
|
|
55
55
|
requests = "2.34.2"
|
|
56
56
|
behave = "^1.2.6"
|
|
57
57
|
|
|
@@ -60,11 +60,13 @@ gitlab-docs = 'src.gitlab_compliance:gitlab_compliance'
|
|
|
60
60
|
gitlab-compliance = 'src.gitlab_compliance:gitlab_compliance'
|
|
61
61
|
|
|
62
62
|
[tool.poetry.group.dev.dependencies]
|
|
63
|
-
setuptools = "
|
|
63
|
+
setuptools = "84.1.0"
|
|
64
64
|
pytest = "^9.0.3"
|
|
65
|
-
|
|
65
|
+
pytest-xdist = "^3.8.0"
|
|
66
|
+
pytest-cov = "^7.1.0"
|
|
67
|
+
pre-commit = "^4.6.2"
|
|
66
68
|
pyyaml = "^6.0.3"
|
|
67
|
-
coverage = "^7.
|
|
69
|
+
coverage = "^7.16.2"
|
|
68
70
|
|
|
69
71
|
[tool.black]
|
|
70
72
|
line-length = 88
|
|
@@ -77,7 +79,7 @@ max-line-length = 88
|
|
|
77
79
|
extend-ignore = ["E203", "W503"]
|
|
78
80
|
|
|
79
81
|
[tool.poetry.group.docs.dependencies]
|
|
80
|
-
zensical = "^0.0.
|
|
82
|
+
zensical = "^0.0.67"
|
|
81
83
|
[build-system]
|
|
82
84
|
requires = ["poetry-core","setuptools","poetry-bumpversion","id"]
|
|
83
85
|
build-backend = "poetry.core.masonry.api"
|
{gitlab_compliance-2.5.0 → gitlab_compliance-2.7.0}/src/compliance/behave_support/environment.py
RENAMED
|
@@ -37,6 +37,10 @@ def before_scenario(context, scenario):
|
|
|
37
37
|
if not context.compliance_entities:
|
|
38
38
|
depth_raw = context.config.userdata.get("max_include_depth", "")
|
|
39
39
|
max_include_depth = int(depth_raw) if str(depth_raw).strip() else None
|
|
40
|
+
generated_raw = context.config.userdata.get("generated_configs", "") or ""
|
|
41
|
+
generated_configs = tuple(
|
|
42
|
+
part.strip() for part in str(generated_raw).split(",") if part.strip()
|
|
43
|
+
)
|
|
40
44
|
context.compliance_entities = load_pipeline_entities(
|
|
41
45
|
pipeline_file=pipeline,
|
|
42
46
|
include_nested=context.config.userdata.get("include_nested", "true")
|
|
@@ -54,6 +58,9 @@ def before_scenario(context, scenario):
|
|
|
54
58
|
resolve_external_includes=_resolve_external_flag(
|
|
55
59
|
context.config.userdata.get("resolve_external_includes", "auto")
|
|
56
60
|
),
|
|
61
|
+
resolve_generated=context.config.userdata.get("resolve_generated", "true")
|
|
62
|
+
== "true",
|
|
63
|
+
generated_configs=generated_configs or None,
|
|
57
64
|
cache=getattr(context, "release_cache", None),
|
|
58
65
|
)
|
|
59
66
|
|
|
@@ -107,6 +107,25 @@ def given_any_container_image_with_release_metadata(context):
|
|
|
107
107
|
)
|
|
108
108
|
|
|
109
109
|
|
|
110
|
+
@given("I have any dynamic child pipeline defined")
|
|
111
|
+
def given_any_dynamic_child_pipeline(context):
|
|
112
|
+
_set_stash(context, context.compliance_entities.get("dynamic_child_pipelines", []))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@given('I have dynamic child pipeline "{name}" defined')
|
|
116
|
+
def given_named_dynamic_child_pipeline(context, name):
|
|
117
|
+
pipelines = [
|
|
118
|
+
item
|
|
119
|
+
for item in context.compliance_entities.get("dynamic_child_pipelines", [])
|
|
120
|
+
if item.get("name") == name or item.get("trigger_job") == name
|
|
121
|
+
]
|
|
122
|
+
_set_stash_or_skip(
|
|
123
|
+
context,
|
|
124
|
+
pipelines,
|
|
125
|
+
skip_reason=f'No dynamic child pipeline named "{name}" found in pipeline',
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
110
129
|
@given("I have any variable defined")
|
|
111
130
|
def given_any_variable(context):
|
|
112
131
|
_set_stash(context, context.compliance_entities.get("variables", []))
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# METADATA
|
|
2
|
+
# title: Baseline job controls
|
|
3
|
+
# description: Core job image and execution rules bundled with gitlab-compliance.
|
|
4
|
+
# custom:
|
|
5
|
+
# id: GLCI-BUILTIN-BASELINE
|
|
6
|
+
# severity: HIGH
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-3
|
|
9
|
+
# - CICD-SEC-7
|
|
10
|
+
# iso27001:
|
|
11
|
+
# - A.8.25
|
|
12
|
+
# - A.8.9
|
|
13
|
+
Feature: Baseline job controls
|
|
14
|
+
|
|
15
|
+
# METADATA
|
|
16
|
+
# title: Job images must not use the latest tag
|
|
17
|
+
# custom:
|
|
18
|
+
# id: GLCI-BUILTIN-BASELINE-01
|
|
19
|
+
# severity: HIGH
|
|
20
|
+
# owasp_cicd:
|
|
21
|
+
# - CICD-SEC-3
|
|
22
|
+
# - CICD-SEC-9
|
|
23
|
+
# iso27001:
|
|
24
|
+
# - A.8.25
|
|
25
|
+
# - A.8.9
|
|
26
|
+
Scenario: Job images must not use the latest tag
|
|
27
|
+
Given I have any job defined
|
|
28
|
+
When it has image
|
|
29
|
+
Then its image must not match ":latest$"
|
|
30
|
+
|
|
31
|
+
# METADATA
|
|
32
|
+
# title: Non-template jobs must define rules
|
|
33
|
+
# custom:
|
|
34
|
+
# id: GLCI-BUILTIN-BASELINE-02
|
|
35
|
+
# severity: HIGH
|
|
36
|
+
# owasp_cicd:
|
|
37
|
+
# - CICD-SEC-1
|
|
38
|
+
# - CICD-SEC-7
|
|
39
|
+
# iso27001:
|
|
40
|
+
# - A.8.9
|
|
41
|
+
# - A.8.32
|
|
42
|
+
Scenario: Non-template jobs must define rules
|
|
43
|
+
Given I have any job defined
|
|
44
|
+
When its name does not start with "."
|
|
45
|
+
Then it must contain rules
|
|
@@ -2,10 +2,27 @@
|
|
|
2
2
|
# title: Component input constraints
|
|
3
3
|
# description: Advanced Scenario Outline for component inputs and conditional fields.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-BUILTIN-COMPONENT
|
|
5
|
+
# id: GLCI-BUILTIN-COMPONENT
|
|
6
6
|
# severity: MEDIUM
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-7
|
|
9
|
+
# - CICD-SEC-8
|
|
10
|
+
# iso27001:
|
|
11
|
+
# - A.8.9
|
|
12
|
+
# - A.8.25
|
|
7
13
|
Feature: Component input constraints
|
|
8
14
|
|
|
15
|
+
# METADATA
|
|
16
|
+
# title: Component input mode constrains dependent fields
|
|
17
|
+
# custom:
|
|
18
|
+
# id: GLCI-BUILTIN-COMPONENT-01
|
|
19
|
+
# severity: MEDIUM
|
|
20
|
+
# owasp_cicd:
|
|
21
|
+
# - CICD-SEC-7
|
|
22
|
+
# - CICD-SEC-8
|
|
23
|
+
# iso27001:
|
|
24
|
+
# - A.8.9
|
|
25
|
+
# - A.8.25
|
|
9
26
|
Scenario Outline: Component input mode constrains dependent fields
|
|
10
27
|
Given I have include type "component" defined
|
|
11
28
|
When the entity input <input> equals <value>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# METADATA
|
|
2
|
+
# title: Include pinning essentials
|
|
3
|
+
# description: Baseline checks for component and fragment version pinning.
|
|
4
|
+
# custom:
|
|
5
|
+
# id: GLCI-BUILTIN-INCPIN
|
|
6
|
+
# severity: HIGH
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-3
|
|
9
|
+
# - CICD-SEC-9
|
|
10
|
+
# iso27001:
|
|
11
|
+
# - A.8.25
|
|
12
|
+
# - A.8.9
|
|
13
|
+
# - A.5.19
|
|
14
|
+
Feature: Include pinning essentials
|
|
15
|
+
|
|
16
|
+
# METADATA
|
|
17
|
+
# title: Component includes must not track a branch
|
|
18
|
+
# custom:
|
|
19
|
+
# id: GLCI-BUILTIN-INCPIN-01
|
|
20
|
+
# severity: HIGH
|
|
21
|
+
# owasp_cicd:
|
|
22
|
+
# - CICD-SEC-3
|
|
23
|
+
# - CICD-SEC-9
|
|
24
|
+
# iso27001:
|
|
25
|
+
# - A.8.25
|
|
26
|
+
# - A.8.9
|
|
27
|
+
# - A.5.19
|
|
28
|
+
Scenario: Component includes must not track a branch
|
|
29
|
+
Given I have include type "component" defined
|
|
30
|
+
Then its version must not match "^(main|master|develop)$"
|
|
31
|
+
|
|
32
|
+
# METADATA
|
|
33
|
+
# title: Component includes must use semver
|
|
34
|
+
# custom:
|
|
35
|
+
# id: GLCI-BUILTIN-INCPIN-02
|
|
36
|
+
# severity: HIGH
|
|
37
|
+
# owasp_cicd:
|
|
38
|
+
# - CICD-SEC-3
|
|
39
|
+
# - CICD-SEC-9
|
|
40
|
+
# iso27001:
|
|
41
|
+
# - A.8.25
|
|
42
|
+
# - A.8.9
|
|
43
|
+
# - A.5.19
|
|
44
|
+
Scenario: Component includes must use semver
|
|
45
|
+
Given I have include type "component" defined
|
|
46
|
+
Then its version must match "^\\d+\\.\\d+\\.\\d+(-[\\w.]+)?$"
|
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
# title: GitLab CI script conventions
|
|
3
3
|
# description: CI-specific hygiene for curl and deprecated variables.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-SHELL-CI
|
|
5
|
+
# id: GLCI-BUILTIN-SHELL-CI
|
|
6
6
|
# severity: MEDIUM
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-7
|
|
9
|
+
# iso27001:
|
|
10
|
+
# - A.8.25
|
|
11
|
+
# - A.8.28
|
|
7
12
|
Feature: GitLab CI script conventions
|
|
8
13
|
|
|
9
14
|
# METADATA
|
|
10
15
|
# title: curl uses fail flag
|
|
11
16
|
# custom:
|
|
12
|
-
# id: GLCI-SHELL-CI-
|
|
17
|
+
# id: GLCI-BUILTIN-SHELL-CI-01
|
|
13
18
|
# severity: MEDIUM
|
|
19
|
+
# owasp_cicd:
|
|
20
|
+
# - CICD-SEC-7
|
|
21
|
+
# iso27001:
|
|
22
|
+
# - A.8.28
|
|
14
23
|
Scenario: curl must use fail flag
|
|
15
24
|
Given I have any job with effective script defined
|
|
16
25
|
Then curl must use fail flag
|
|
@@ -18,8 +27,13 @@ Feature: GitLab CI script conventions
|
|
|
18
27
|
# METADATA
|
|
19
28
|
# title: Deprecated CI_BUILD variables are not used
|
|
20
29
|
# custom:
|
|
21
|
-
# id: GLCI-SHELL-CI-
|
|
30
|
+
# id: GLCI-BUILTIN-SHELL-CI-02
|
|
22
31
|
# severity: MEDIUM
|
|
32
|
+
# owasp_cicd:
|
|
33
|
+
# - CICD-SEC-7
|
|
34
|
+
# iso27001:
|
|
35
|
+
# - A.8.9
|
|
36
|
+
# - A.8.25
|
|
23
37
|
Scenario: Deprecated CI_BUILD variables must not be used
|
|
24
38
|
Given I have any job with effective script defined
|
|
25
39
|
Then deprecated CI_BUILD variables must not be used
|
|
@@ -27,8 +41,12 @@ Feature: GitLab CI script conventions
|
|
|
27
41
|
# METADATA
|
|
28
42
|
# title: CI variables should be quoted
|
|
29
43
|
# custom:
|
|
30
|
-
# id: GLCI-SHELL-CI-
|
|
44
|
+
# id: GLCI-BUILTIN-SHELL-CI-03
|
|
31
45
|
# severity: MEDIUM
|
|
46
|
+
# owasp_cicd:
|
|
47
|
+
# - CICD-SEC-7
|
|
48
|
+
# iso27001:
|
|
49
|
+
# - A.8.28
|
|
32
50
|
Scenario: CI variables should be quoted
|
|
33
51
|
Given I have any job with effective script defined
|
|
34
52
|
Then user supplied variables must be quoted or validated
|
|
@@ -2,15 +2,23 @@
|
|
|
2
2
|
# title: Command substitution standards
|
|
3
3
|
# description: Prefer modern dollar-parentheses substitution over backticks.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-SHELL-SUB
|
|
5
|
+
# id: GLCI-BUILTIN-SHELL-SUB
|
|
6
6
|
# severity: MEDIUM
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-7
|
|
9
|
+
# iso27001:
|
|
10
|
+
# - A.8.28
|
|
7
11
|
Feature: Command substitution
|
|
8
12
|
|
|
9
13
|
# METADATA
|
|
10
14
|
# title: Legacy backticks are not used
|
|
11
15
|
# custom:
|
|
12
|
-
# id: GLCI-SHELL-SUB-
|
|
16
|
+
# id: GLCI-BUILTIN-SHELL-SUB-01
|
|
13
17
|
# severity: MEDIUM
|
|
18
|
+
# owasp_cicd:
|
|
19
|
+
# - CICD-SEC-7
|
|
20
|
+
# iso27001:
|
|
21
|
+
# - A.8.28
|
|
14
22
|
Scenario: Legacy backticks are not used
|
|
15
23
|
Given I have any job with effective script defined
|
|
16
24
|
Then command substitution must use dollar parentheses
|
|
@@ -18,8 +26,12 @@ Feature: Command substitution
|
|
|
18
26
|
# METADATA
|
|
19
27
|
# title: Nested command substitution is readable
|
|
20
28
|
# custom:
|
|
21
|
-
# id: GLCI-SHELL-SUB-
|
|
29
|
+
# id: GLCI-BUILTIN-SHELL-SUB-02
|
|
22
30
|
# severity: MEDIUM
|
|
31
|
+
# owasp_cicd:
|
|
32
|
+
# - CICD-SEC-7
|
|
33
|
+
# iso27001:
|
|
34
|
+
# - A.8.28
|
|
23
35
|
Scenario: Nested command substitution is readable
|
|
24
36
|
Given I have any job with effective script defined
|
|
25
37
|
Then nested command substitution must use dollar parentheses
|
|
@@ -2,15 +2,23 @@
|
|
|
2
2
|
# title: Conditional expression standards
|
|
3
3
|
# description: Portable and safely quoted test expressions.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-SHELL-TEST
|
|
5
|
+
# id: GLCI-BUILTIN-SHELL-TEST
|
|
6
6
|
# severity: MEDIUM
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-7
|
|
9
|
+
# iso27001:
|
|
10
|
+
# - A.8.28
|
|
7
11
|
Feature: Conditional expressions
|
|
8
12
|
|
|
9
13
|
# METADATA
|
|
10
14
|
# title: Test operators are portable
|
|
11
15
|
# custom:
|
|
12
|
-
# id: GLCI-SHELL-TEST-
|
|
16
|
+
# id: GLCI-BUILTIN-SHELL-TEST-01
|
|
13
17
|
# severity: MEDIUM
|
|
18
|
+
# owasp_cicd:
|
|
19
|
+
# - CICD-SEC-7
|
|
20
|
+
# iso27001:
|
|
21
|
+
# - A.8.28
|
|
14
22
|
Scenario: Test operators are portable
|
|
15
23
|
Given I have any job with effective script defined
|
|
16
24
|
Then POSIX compliant operators must be used
|
|
@@ -18,8 +26,12 @@ Feature: Conditional expressions
|
|
|
18
26
|
# METADATA
|
|
19
27
|
# title: Variables are quoted in test statements
|
|
20
28
|
# custom:
|
|
21
|
-
# id: GLCI-SHELL-TEST-
|
|
29
|
+
# id: GLCI-BUILTIN-SHELL-TEST-02
|
|
22
30
|
# severity: HIGH
|
|
31
|
+
# owasp_cicd:
|
|
32
|
+
# - CICD-SEC-7
|
|
33
|
+
# iso27001:
|
|
34
|
+
# - A.8.28
|
|
23
35
|
Scenario: Variables are quoted in test statements
|
|
24
36
|
Given I have any job with effective script defined
|
|
25
37
|
Then variables in test expressions must be quoted
|
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
# title: Error handling
|
|
3
3
|
# description: Strict mode and exit-code handling for GitLab CI job scripts.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-SHELL-ERR
|
|
5
|
+
# id: GLCI-BUILTIN-SHELL-ERR
|
|
6
6
|
# severity: HIGH
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-7
|
|
9
|
+
# iso27001:
|
|
10
|
+
# - A.8.28
|
|
11
|
+
# - A.8.25
|
|
7
12
|
Feature: Error handling
|
|
8
13
|
|
|
9
14
|
# METADATA
|
|
10
15
|
# title: Scripts use strict mode
|
|
11
16
|
# custom:
|
|
12
|
-
# id: GLCI-SHELL-ERR-
|
|
17
|
+
# id: GLCI-BUILTIN-SHELL-ERR-01
|
|
13
18
|
# severity: MEDIUM
|
|
19
|
+
# owasp_cicd:
|
|
20
|
+
# - CICD-SEC-7
|
|
21
|
+
# iso27001:
|
|
22
|
+
# - A.8.28
|
|
14
23
|
Scenario: Multi-line scripts use strict mode
|
|
15
24
|
Given I have any job with effective script defined
|
|
16
25
|
When the effective script has more than 1 line
|
|
@@ -19,8 +28,12 @@ Feature: Error handling
|
|
|
19
28
|
# METADATA
|
|
20
29
|
# title: Commands return meaningful exit codes
|
|
21
30
|
# custom:
|
|
22
|
-
# id: GLCI-SHELL-ERR-
|
|
31
|
+
# id: GLCI-BUILTIN-SHELL-ERR-02
|
|
23
32
|
# severity: MEDIUM
|
|
33
|
+
# owasp_cicd:
|
|
34
|
+
# - CICD-SEC-7
|
|
35
|
+
# iso27001:
|
|
36
|
+
# - A.8.28
|
|
24
37
|
Scenario: Commands return meaningful exit codes
|
|
25
38
|
Given I have any job with effective script defined
|
|
26
39
|
Then failure must be handled explicitly
|
|
@@ -28,8 +41,12 @@ Feature: Error handling
|
|
|
28
41
|
# METADATA
|
|
29
42
|
# title: Functions propagate failures
|
|
30
43
|
# custom:
|
|
31
|
-
# id: GLCI-SHELL-ERR-
|
|
44
|
+
# id: GLCI-BUILTIN-SHELL-ERR-03
|
|
32
45
|
# severity: MEDIUM
|
|
46
|
+
# owasp_cicd:
|
|
47
|
+
# - CICD-SEC-7
|
|
48
|
+
# iso27001:
|
|
49
|
+
# - A.8.28
|
|
33
50
|
Scenario: Functions propagate failures
|
|
34
51
|
Given I have any job with effective script defined
|
|
35
52
|
Then functions must propagate failures
|
|
@@ -2,15 +2,23 @@
|
|
|
2
2
|
# title: Safe file operations
|
|
3
3
|
# description: Quoted paths, secure temps, and protected recursive rm.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-SHELL-FILE
|
|
5
|
+
# id: GLCI-BUILTIN-SHELL-FILE
|
|
6
6
|
# severity: HIGH
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-7
|
|
9
|
+
# iso27001:
|
|
10
|
+
# - A.8.28
|
|
7
11
|
Feature: Safe file operations
|
|
8
12
|
|
|
9
13
|
# METADATA
|
|
10
14
|
# title: File paths are quoted
|
|
11
15
|
# custom:
|
|
12
|
-
# id: GLCI-SHELL-FILE-
|
|
16
|
+
# id: GLCI-BUILTIN-SHELL-FILE-01
|
|
13
17
|
# severity: HIGH
|
|
18
|
+
# owasp_cicd:
|
|
19
|
+
# - CICD-SEC-7
|
|
20
|
+
# iso27001:
|
|
21
|
+
# - A.8.28
|
|
14
22
|
Scenario: File paths are quoted
|
|
15
23
|
Given I have any job with effective script defined
|
|
16
24
|
Then file paths must be quoted
|
|
@@ -18,8 +26,12 @@ Feature: Safe file operations
|
|
|
18
26
|
# METADATA
|
|
19
27
|
# title: Temporary files are securely created
|
|
20
28
|
# custom:
|
|
21
|
-
# id: GLCI-SHELL-FILE-
|
|
29
|
+
# id: GLCI-BUILTIN-SHELL-FILE-02
|
|
22
30
|
# severity: HIGH
|
|
31
|
+
# owasp_cicd:
|
|
32
|
+
# - CICD-SEC-7
|
|
33
|
+
# iso27001:
|
|
34
|
+
# - A.8.28
|
|
23
35
|
Scenario: Temporary files are securely created
|
|
24
36
|
Given I have any job with effective script defined
|
|
25
37
|
When temporary files are required
|
|
@@ -28,8 +40,12 @@ Feature: Safe file operations
|
|
|
28
40
|
# METADATA
|
|
29
41
|
# title: Dangerous rm operations are protected
|
|
30
42
|
# custom:
|
|
31
|
-
# id: GLCI-SHELL-FILE-
|
|
43
|
+
# id: GLCI-BUILTIN-SHELL-FILE-03
|
|
32
44
|
# severity: HIGH
|
|
45
|
+
# owasp_cicd:
|
|
46
|
+
# - CICD-SEC-7
|
|
47
|
+
# iso27001:
|
|
48
|
+
# - A.8.28
|
|
33
49
|
Scenario: Dangerous rm operations are protected
|
|
34
50
|
Given I have any job with effective script defined
|
|
35
51
|
When rm is used recursively
|
|
@@ -2,15 +2,27 @@
|
|
|
2
2
|
# title: CI script dependency pinning
|
|
3
3
|
# description: Supply-chain pinning controls for packages and downloads in CI scripts.
|
|
4
4
|
# custom:
|
|
5
|
-
# id: GLCI-SHELL-PIN
|
|
5
|
+
# id: GLCI-BUILTIN-SHELL-PIN
|
|
6
6
|
# severity: HIGH
|
|
7
|
+
# owasp_cicd:
|
|
8
|
+
# - CICD-SEC-3
|
|
9
|
+
# - CICD-SEC-9
|
|
10
|
+
# iso27001:
|
|
11
|
+
# - A.8.25
|
|
12
|
+
# - A.8.9
|
|
7
13
|
Feature: CI script dependency pinning
|
|
8
14
|
|
|
9
15
|
# METADATA
|
|
10
16
|
# title: Downloads must verify checksums
|
|
11
17
|
# custom:
|
|
12
|
-
# id: GLCI-SHELL-PIN-
|
|
18
|
+
# id: GLCI-BUILTIN-SHELL-PIN-01
|
|
13
19
|
# severity: HIGH
|
|
20
|
+
# owasp_cicd:
|
|
21
|
+
# - CICD-SEC-3
|
|
22
|
+
# - CICD-SEC-9
|
|
23
|
+
# iso27001:
|
|
24
|
+
# - A.8.25
|
|
25
|
+
# - A.8.9
|
|
14
26
|
Scenario: Script downloads must verify checksums
|
|
15
27
|
Given I have any job with effective script defined
|
|
16
28
|
Then script downloads must verify checksums
|
|
@@ -18,8 +30,14 @@ Feature: CI script dependency pinning
|
|
|
18
30
|
# METADATA
|
|
19
31
|
# title: Disallow remote pipe to shell
|
|
20
32
|
# custom:
|
|
21
|
-
# id: GLCI-SHELL-PIN-
|
|
33
|
+
# id: GLCI-BUILTIN-SHELL-PIN-02
|
|
22
34
|
# severity: HIGH
|
|
35
|
+
# owasp_cicd:
|
|
36
|
+
# - CICD-SEC-3
|
|
37
|
+
# - CICD-SEC-4
|
|
38
|
+
# iso27001:
|
|
39
|
+
# - A.8.28
|
|
40
|
+
# - A.8.25
|
|
23
41
|
Scenario: Scripts must not pipe remote downloads to a shell
|
|
24
42
|
Given I have any job with effective script defined
|
|
25
43
|
Then untrusted remote scripts must not be executed
|
|
@@ -28,8 +46,14 @@ Feature: CI script dependency pinning
|
|
|
28
46
|
# title: pip packages must be version-pinned
|
|
29
47
|
# description: Applies to both pip and pip3 install commands in job scripts.
|
|
30
48
|
# custom:
|
|
31
|
-
# id: GLCI-SHELL-PIN-
|
|
49
|
+
# id: GLCI-BUILTIN-SHELL-PIN-03
|
|
32
50
|
# severity: MEDIUM
|
|
51
|
+
# owasp_cicd:
|
|
52
|
+
# - CICD-SEC-3
|
|
53
|
+
# - CICD-SEC-9
|
|
54
|
+
# iso27001:
|
|
55
|
+
# - A.8.25
|
|
56
|
+
# - A.8.9
|
|
33
57
|
Scenario: pip install must pin package versions
|
|
34
58
|
Given I have any job with effective script defined
|
|
35
59
|
Then package installs of type "pip" must use pinned versions
|
|
@@ -37,8 +61,14 @@ Feature: CI script dependency pinning
|
|
|
37
61
|
# METADATA
|
|
38
62
|
# title: apk packages must be version-pinned
|
|
39
63
|
# custom:
|
|
40
|
-
# id: GLCI-SHELL-PIN-
|
|
64
|
+
# id: GLCI-BUILTIN-SHELL-PIN-04
|
|
41
65
|
# severity: MEDIUM
|
|
66
|
+
# owasp_cicd:
|
|
67
|
+
# - CICD-SEC-3
|
|
68
|
+
# - CICD-SEC-9
|
|
69
|
+
# iso27001:
|
|
70
|
+
# - A.8.25
|
|
71
|
+
# - A.8.9
|
|
42
72
|
Scenario: apk add must pin package versions
|
|
43
73
|
Given I have any job with effective script defined
|
|
44
74
|
Then package installs of type "apk" must use pinned versions
|
|
@@ -46,8 +76,14 @@ Feature: CI script dependency pinning
|
|
|
46
76
|
# METADATA
|
|
47
77
|
# title: apt packages must be version-pinned
|
|
48
78
|
# custom:
|
|
49
|
-
# id: GLCI-SHELL-PIN-
|
|
79
|
+
# id: GLCI-BUILTIN-SHELL-PIN-05
|
|
50
80
|
# severity: MEDIUM
|
|
81
|
+
# owasp_cicd:
|
|
82
|
+
# - CICD-SEC-3
|
|
83
|
+
# - CICD-SEC-9
|
|
84
|
+
# iso27001:
|
|
85
|
+
# - A.8.25
|
|
86
|
+
# - A.8.9
|
|
51
87
|
Scenario: apt-get install must pin package versions
|
|
52
88
|
Given I have any job with effective script defined
|
|
53
89
|
Then package installs of type "apt" must use pinned versions
|
|
@@ -55,8 +91,14 @@ Feature: CI script dependency pinning
|
|
|
55
91
|
# METADATA
|
|
56
92
|
# title: npm global packages must be version-pinned
|
|
57
93
|
# custom:
|
|
58
|
-
# id: GLCI-SHELL-PIN-
|
|
94
|
+
# id: GLCI-BUILTIN-SHELL-PIN-06
|
|
59
95
|
# severity: MEDIUM
|
|
96
|
+
# owasp_cicd:
|
|
97
|
+
# - CICD-SEC-3
|
|
98
|
+
# - CICD-SEC-9
|
|
99
|
+
# iso27001:
|
|
100
|
+
# - A.8.25
|
|
101
|
+
# - A.8.9
|
|
60
102
|
Scenario: npm global installs must pin package versions
|
|
61
103
|
Given I have any job with effective script defined
|
|
62
104
|
Then package installs of type "npm" must use pinned versions
|
|
@@ -64,8 +106,14 @@ Feature: CI script dependency pinning
|
|
|
64
106
|
# METADATA
|
|
65
107
|
# title: go install must pin versions
|
|
66
108
|
# custom:
|
|
67
|
-
# id: GLCI-SHELL-PIN-
|
|
109
|
+
# id: GLCI-BUILTIN-SHELL-PIN-07
|
|
68
110
|
# severity: MEDIUM
|
|
111
|
+
# owasp_cicd:
|
|
112
|
+
# - CICD-SEC-3
|
|
113
|
+
# - CICD-SEC-9
|
|
114
|
+
# iso27001:
|
|
115
|
+
# - A.8.25
|
|
116
|
+
# - A.8.9
|
|
69
117
|
Scenario: go install must pin module versions
|
|
70
118
|
Given I have any job with effective script defined
|
|
71
119
|
Then package installs of type "go" must use pinned versions
|
|
@@ -73,8 +121,14 @@ Feature: CI script dependency pinning
|
|
|
73
121
|
# METADATA
|
|
74
122
|
# title: git clone must verify revision
|
|
75
123
|
# custom:
|
|
76
|
-
# id: GLCI-SHELL-PIN-
|
|
124
|
+
# id: GLCI-BUILTIN-SHELL-PIN-08
|
|
77
125
|
# severity: MEDIUM
|
|
126
|
+
# owasp_cicd:
|
|
127
|
+
# - CICD-SEC-3
|
|
128
|
+
# - CICD-SEC-9
|
|
129
|
+
# iso27001:
|
|
130
|
+
# - A.8.25
|
|
131
|
+
# - A.8.9
|
|
78
132
|
Scenario: git clone must verify commit or tag
|
|
79
133
|
Given I have any job with effective script defined
|
|
80
134
|
Then git clone must verify commit or tag
|
|
@@ -83,8 +137,14 @@ Feature: CI script dependency pinning
|
|
|
83
137
|
# title: docker run and pull must pin images
|
|
84
138
|
# description: Script docker commands must reference an explicit tag or sha256 digest.
|
|
85
139
|
# custom:
|
|
86
|
-
# id: GLCI-SHELL-PIN-
|
|
140
|
+
# id: GLCI-BUILTIN-SHELL-PIN-09
|
|
87
141
|
# severity: MEDIUM
|
|
142
|
+
# owasp_cicd:
|
|
143
|
+
# - CICD-SEC-3
|
|
144
|
+
# - CICD-SEC-9
|
|
145
|
+
# iso27001:
|
|
146
|
+
# - A.8.25
|
|
147
|
+
# - A.8.9
|
|
88
148
|
Scenario: docker run and pull must pin container images
|
|
89
149
|
Given I have any job with effective script defined
|
|
90
150
|
Then docker commands must pin container images to a tag or sha256 digest
|
|
@@ -93,8 +153,14 @@ Feature: CI script dependency pinning
|
|
|
93
153
|
# title: yum/dnf packages must be version-pinned
|
|
94
154
|
# description: Applies to yum, dnf, and microdnf install commands in job scripts.
|
|
95
155
|
# custom:
|
|
96
|
-
# id: GLCI-SHELL-PIN-
|
|
156
|
+
# id: GLCI-BUILTIN-SHELL-PIN-10
|
|
97
157
|
# severity: MEDIUM
|
|
158
|
+
# owasp_cicd:
|
|
159
|
+
# - CICD-SEC-3
|
|
160
|
+
# - CICD-SEC-9
|
|
161
|
+
# iso27001:
|
|
162
|
+
# - A.8.25
|
|
163
|
+
# - A.8.9
|
|
98
164
|
Scenario: yum and dnf install must pin package versions
|
|
99
165
|
Given I have any job with effective script defined
|
|
100
166
|
Then package installs of type "yum" must use pinned versions
|