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.
Files changed (36) hide show
  1. fluidattacks_core_models-14.3.0/.envrc +1 -0
  2. fluidattacks_core_models-14.3.0/.gitignore +11 -0
  3. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/PKG-INFO +1 -1
  4. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/cspm_config.py +14 -4
  5. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/loader.py +4 -1
  6. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/pyproject.toml +1 -1
  7. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_loader_env.py +74 -2
  8. fluidattacks_core_models-14.2.0/.envrc +0 -1
  9. fluidattacks_core_models-14.2.0/.gitignore +0 -9
  10. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/__init__.py +0 -0
  11. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/py.typed +0 -0
  12. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/__init__.py +0 -0
  13. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/apk_config.py +0 -0
  14. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/common_config.py +0 -0
  15. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/containers_sca_config.py +0 -0
  16. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/dast_config.py +0 -0
  17. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/resolves_config.py +0 -0
  18. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sast_config.py +0 -0
  19. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sbom_config.py +0 -0
  20. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sca_config.py +0 -0
  21. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/scan_config.py +0 -0
  22. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sniffs_config.py +0 -0
  23. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/scanners/sspm_config.py +0 -0
  24. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/__init__.py +0 -0
  25. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/component_orchestrator.py +0 -0
  26. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/root_scanner.py +0 -0
  27. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/fluidattacks_core/models/state_machines/types.py +0 -0
  28. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/import-linter.cfg +0 -0
  29. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/mypy.ini +0 -0
  30. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/ruff.toml +0 -0
  31. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/__init__.py +0 -0
  32. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_component_orchestrator.py +0 -0
  33. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_model_scanner.py +0 -0
  34. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_root_scanner.py +0 -0
  35. {fluidattacks_core_models-14.2.0 → fluidattacks_core_models-14.3.0}/tests/test_state_machines.py +0 -0
  36. {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
@@ -0,0 +1,11 @@
1
+ dist/
2
+ dist-*/
3
+ /.cargo-cache
4
+ target/
5
+ .direnv/
6
+ .venv/
7
+ .vscode/settings.json
8
+ .zed/settings.json
9
+ # each package's shell writes its own, beside the package rather than here
10
+ **/.vscode/settings.json
11
+ *.so
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: fluidattacks_core_models
3
- Version: 14.2.0
3
+ Version: 14.3.0
4
4
  Summary: Fluid Attacks Core Models Library
5
5
  Author-email: Development <development@fluidattacks.com>
6
6
  License: MPL-2.0
@@ -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", "session_token", mode="before")
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", "external_id", mode="before")
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)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fluidattacks_core_models"
3
- version = "14.2.0"
3
+ version = "14.3.0"
4
4
  description = "Fluid Attacks Core Models Library"
5
5
  authors = [{ name = "Development", email = "development@fluidattacks.com" }]
6
6
  license = { text = "MPL-2.0" }
@@ -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 test_build_config_missing_var_resolves_to_none(
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"
@@ -1,9 +0,0 @@
1
- dist/
2
- dist-*/
3
- /.cargo-cache
4
- target/
5
- .direnv/
6
- .venv/
7
- .vscode/settings.json
8
- .zed/settings.json
9
- *.so