fluidattacks_core_models 14.2.0__tar.gz → 14.3.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.
- fluidattacks_core_models-14.3.0/.envrc +1 -0
- fluidattacks_core_models-14.3.0/.gitignore +11 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/PKG-INFO +1 -1
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/cspm_config.py +14 -4
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/loader.py +4 -1
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/pyproject.toml +1 -1
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_loader_env.py +74 -2
- fluidattacks_core_models-14.2.0/.envrc +0 -1
- fluidattacks_core_models-14.2.0/.gitignore +0 -9
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/__init__.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/py.typed +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/__init__.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/apk_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/common_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/containers_sca_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/dast_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/resolves_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sast_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sbom_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sca_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/scan_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sniffs_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sspm_config.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/__init__.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/component_orchestrator.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/root_scanner.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/types.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/import-linter.cfg +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/mypy.ini +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/ruff.toml +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/__init__.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_component_orchestrator.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_model_scanner.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_root_scanner.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_state_machines.py +0 -0
- {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/uv.lock +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
use flake ../../..#fluidattacks-core-models
|
|
@@ -6,15 +6,20 @@ from fluidattacks_core.models.scanners.loader import LoaderValidationInfo, resol
|
|
|
6
6
|
class AwsCredentials(BaseModel):
|
|
7
7
|
model_config = {"extra": "forbid"}
|
|
8
8
|
access_key_id: str
|
|
9
|
-
secret_access_key: str
|
|
10
|
-
session_token: str | None = None
|
|
9
|
+
secret_access_key: str = Field(repr=False)
|
|
10
|
+
session_token: str | None = Field(default=None, repr=False)
|
|
11
11
|
environment_id: str | None = None
|
|
12
12
|
|
|
13
|
-
@field_validator("access_key_id", "secret_access_key",
|
|
13
|
+
@field_validator("access_key_id", "secret_access_key", mode="before")
|
|
14
14
|
@classmethod
|
|
15
15
|
def _resolve_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
|
|
16
16
|
return resolve_env_var(v, info)
|
|
17
17
|
|
|
18
|
+
@field_validator("session_token", mode="before")
|
|
19
|
+
@classmethod
|
|
20
|
+
def _resolve_optional_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
|
|
21
|
+
return resolve_env_var(v, info, required=False)
|
|
22
|
+
|
|
18
23
|
@model_validator(mode="after")
|
|
19
24
|
def _validate_key_session_token_pairing(self) -> "AwsCredentials":
|
|
20
25
|
is_temporary = self.access_key_id.startswith("ASIA")
|
|
@@ -33,11 +38,16 @@ class AwsRole(BaseModel):
|
|
|
33
38
|
external_id: str | None = Field(default=None, repr=False)
|
|
34
39
|
environment_id: str | None = None
|
|
35
40
|
|
|
36
|
-
@field_validator("role",
|
|
41
|
+
@field_validator("role", mode="before")
|
|
37
42
|
@classmethod
|
|
38
43
|
def _resolve_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
|
|
39
44
|
return resolve_env_var(v, info)
|
|
40
45
|
|
|
46
|
+
@field_validator("external_id", mode="before")
|
|
47
|
+
@classmethod
|
|
48
|
+
def _resolve_optional_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
|
|
49
|
+
return resolve_env_var(v, info, required=False)
|
|
50
|
+
|
|
41
51
|
|
|
42
52
|
class CspmConfig(BaseModel):
|
|
43
53
|
model_config = {"extra": "forbid"}
|
|
@@ -28,7 +28,7 @@ def _sub_env_var(m: re.Match[str]) -> str:
|
|
|
28
28
|
return value
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
def resolve_env_var(v: object, info: LoaderValidationInfo) -> object:
|
|
31
|
+
def resolve_env_var(v: object, info: LoaderValidationInfo, *, required: bool = True) -> object:
|
|
32
32
|
if not isinstance(v, str) or not (info.context or {}).get("resolve_env"):
|
|
33
33
|
return v
|
|
34
34
|
matches = list(_ENV_PLACEHOLDER.finditer(v))
|
|
@@ -39,6 +39,9 @@ def resolve_env_var(v: object, info: LoaderValidationInfo) -> object:
|
|
|
39
39
|
var_name = matches[0].group(1)
|
|
40
40
|
value = os.environ.get(var_name)
|
|
41
41
|
if value is None:
|
|
42
|
+
if required:
|
|
43
|
+
msg = f"environment variable '{var_name}' referenced in the scan config is not set"
|
|
44
|
+
raise ValueError(msg)
|
|
42
45
|
LOGGER.warning("env var '%s' not set; field will be None", var_name)
|
|
43
46
|
return None
|
|
44
47
|
LOGGER.info("env var '%s' set", var_name)
|
{fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_loader_env.py
RENAMED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
-
from pydantic import BaseModel, field_validator
|
|
4
|
+
from pydantic import BaseModel, ValidationError, field_validator
|
|
5
5
|
|
|
6
|
+
from fluidattacks_core.models.scanners import AwsCredentials, AwsRole, CspmConfig
|
|
6
7
|
from fluidattacks_core.models.scanners.loader import (
|
|
7
8
|
LoaderValidationInfo,
|
|
8
9
|
build_config,
|
|
@@ -22,6 +23,16 @@ class _SecretFixture(BaseModel):
|
|
|
22
23
|
value: str | None = None
|
|
23
24
|
namespace: str = ""
|
|
24
25
|
|
|
26
|
+
@field_validator("value", mode="before")
|
|
27
|
+
@classmethod
|
|
28
|
+
def _resolve_value(cls, v: object, info: LoaderValidationInfo) -> object:
|
|
29
|
+
return resolve_env_var(v, info, required=False)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _RequiredSecretFixture(BaseModel):
|
|
33
|
+
model_config = {"extra": "forbid"}
|
|
34
|
+
value: str
|
|
35
|
+
|
|
25
36
|
@field_validator("value", mode="before")
|
|
26
37
|
@classmethod
|
|
27
38
|
def _resolve_value(cls, v: object, info: LoaderValidationInfo) -> object:
|
|
@@ -45,7 +56,7 @@ def test_build_config_resolves_sensitive_field(
|
|
|
45
56
|
assert cfg.value == "resolved-value"
|
|
46
57
|
|
|
47
58
|
|
|
48
|
-
def
|
|
59
|
+
def test_build_config_missing_var_on_optional_field_resolves_to_none(
|
|
49
60
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
50
61
|
) -> None:
|
|
51
62
|
monkeypatch.delenv("TOKEN", raising=False)
|
|
@@ -54,6 +65,58 @@ def test_build_config_missing_var_resolves_to_none(
|
|
|
54
65
|
assert cfg.value is None
|
|
55
66
|
|
|
56
67
|
|
|
68
|
+
def test_build_config_set_var_on_required_field_resolves(
|
|
69
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
70
|
+
) -> None:
|
|
71
|
+
monkeypatch.setenv("TOKEN", "resolved-value")
|
|
72
|
+
path = _write(tmp_path, "value: ${TOKEN}\n")
|
|
73
|
+
cfg = build_config(path, _RequiredSecretFixture)
|
|
74
|
+
assert cfg.value == "resolved-value"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_build_config_missing_var_on_required_field_names_the_variable(
|
|
78
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
79
|
+
) -> None:
|
|
80
|
+
monkeypatch.delenv("TOKEN", raising=False)
|
|
81
|
+
path = _write(tmp_path, "value: ${TOKEN}\n")
|
|
82
|
+
with pytest.raises(ValidationError) as exc_info:
|
|
83
|
+
build_config(path, _RequiredSecretFixture)
|
|
84
|
+
assert "environment variable 'TOKEN' referenced in the scan config is not set" in str(
|
|
85
|
+
exc_info.value
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_build_config_missing_var_on_cspm_external_id_resolves_to_none(
|
|
90
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
91
|
+
) -> None:
|
|
92
|
+
monkeypatch.delenv("CSPM_AWS_EXTERNAL_ID", raising=False)
|
|
93
|
+
path = _write(
|
|
94
|
+
tmp_path,
|
|
95
|
+
"aws_credentials:\n"
|
|
96
|
+
" - role: arn:aws:iam::123456789012:role/MyRole\n"
|
|
97
|
+
" external_id: ${CSPM_AWS_EXTERNAL_ID}\n",
|
|
98
|
+
)
|
|
99
|
+
role = build_config(path, CspmConfig).aws_credentials[0]
|
|
100
|
+
assert isinstance(role, AwsRole)
|
|
101
|
+
assert role.external_id is None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def test_build_config_missing_var_on_cspm_session_token_resolves_to_none(
|
|
105
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
106
|
+
) -> None:
|
|
107
|
+
monkeypatch.delenv("CSPM_AWS_SESSION_TOKEN", raising=False)
|
|
108
|
+
path = _write(
|
|
109
|
+
tmp_path,
|
|
110
|
+
"aws_credentials:\n"
|
|
111
|
+
" - access_key_id: AKIA-fake-key\n"
|
|
112
|
+
" secret_access_key: secret\n"
|
|
113
|
+
" session_token: ${CSPM_AWS_SESSION_TOKEN}\n",
|
|
114
|
+
)
|
|
115
|
+
cred = build_config(path, CspmConfig).aws_credentials[0]
|
|
116
|
+
assert isinstance(cred, AwsCredentials)
|
|
117
|
+
assert cred.session_token is None
|
|
118
|
+
|
|
119
|
+
|
|
57
120
|
def test_build_config_non_sensitive_field_stays_literal(
|
|
58
121
|
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
59
122
|
) -> None:
|
|
@@ -87,6 +150,15 @@ def test_partial_missing_var_substitutes_empty_string(
|
|
|
87
150
|
assert cfg.value == "https:///api"
|
|
88
151
|
|
|
89
152
|
|
|
153
|
+
def test_partial_missing_var_on_required_field_substitutes_empty_string(
|
|
154
|
+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
155
|
+
) -> None:
|
|
156
|
+
monkeypatch.delenv("HOST", raising=False)
|
|
157
|
+
path = _write(tmp_path, "value: https://${HOST}/api\n")
|
|
158
|
+
cfg = build_config(path, _RequiredSecretFixture)
|
|
159
|
+
assert cfg.value == "https:///api"
|
|
160
|
+
|
|
161
|
+
|
|
90
162
|
def test_multi_var_resolved(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
91
163
|
monkeypatch.setenv("A", "foo")
|
|
92
164
|
monkeypatch.setenv("B", "bar")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
use_flake ".#python311.devShell"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_model_scanner.py
RENAMED
|
File without changes
|
{fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_root_scanner.py
RENAMED
|
File without changes
|
{fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_state_machines.py
RENAMED
|
File without changes
|
|
File without changes
|