fluidattacks_core_models 12.0.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 (34) hide show
  1. fluidattacks_core_models-12.0.0/.envrc +1 -0
  2. fluidattacks_core_models-12.0.0/.gitignore +5 -0
  3. fluidattacks_core_models-12.0.0/PKG-INFO +15 -0
  4. fluidattacks_core_models-12.0.0/build/default.nix +19 -0
  5. fluidattacks_core_models-12.0.0/build/filter.nix +13 -0
  6. fluidattacks_core_models-12.0.0/flake.lock +303 -0
  7. fluidattacks_core_models-12.0.0/flake.nix +29 -0
  8. fluidattacks_core_models-12.0.0/fluidattacks_core/models/__init__.py +0 -0
  9. fluidattacks_core_models-12.0.0/fluidattacks_core/models/py.typed +0 -0
  10. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/__init__.py +67 -0
  11. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/apk_config.py +26 -0
  12. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/common_config.py +27 -0
  13. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/containers_sca_config.py +37 -0
  14. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/cspm_config.py +45 -0
  15. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/dast_config.py +47 -0
  16. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/loader.py +74 -0
  17. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/sast_config.py +15 -0
  18. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/sbom_config.py +57 -0
  19. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/sca_config.py +16 -0
  20. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/scan_config.py +39 -0
  21. fluidattacks_core_models-12.0.0/fluidattacks_core/models/scanners/sniffs_config.py +9 -0
  22. fluidattacks_core_models-12.0.0/fluidattacks_core/models/state_machines/__init__.py +35 -0
  23. fluidattacks_core_models-12.0.0/fluidattacks_core/models/state_machines/root_scanner.py +105 -0
  24. fluidattacks_core_models-12.0.0/fluidattacks_core/models/state_machines/types.py +99 -0
  25. fluidattacks_core_models-12.0.0/import-linter.cfg +22 -0
  26. fluidattacks_core_models-12.0.0/mypy.ini +32 -0
  27. fluidattacks_core_models-12.0.0/pyproject.toml +40 -0
  28. fluidattacks_core_models-12.0.0/ruff.toml +45 -0
  29. fluidattacks_core_models-12.0.0/tests/__init__.py +0 -0
  30. fluidattacks_core_models-12.0.0/tests/test_loader_env.py +109 -0
  31. fluidattacks_core_models-12.0.0/tests/test_model_scanner.py +747 -0
  32. fluidattacks_core_models-12.0.0/tests/test_root_scanner.py +346 -0
  33. fluidattacks_core_models-12.0.0/tests/test_state_machines.py +237 -0
  34. fluidattacks_core_models-12.0.0/uv.lock +892 -0
@@ -0,0 +1 @@
1
+ use_flake ".#python311.devShell"
@@ -0,0 +1,5 @@
1
+ target/
2
+ .direnv/
3
+ .venv/
4
+ .vscode/settings.json
5
+ .zed/settings.json
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.5
2
+ Name: fluidattacks_core_models
3
+ Version: 12.0.0
4
+ Summary: Fluid Attacks Core Models Library
5
+ Author-email: Development <development@fluidattacks.com>
6
+ License: MPL-2.0
7
+ Classifier: Development Status :: 1 - Planning
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Requires-Python: >=3.11
14
+ Requires-Dist: pydantic>=2.12.3
15
+ Requires-Dist: pyyaml>=6.0.2
@@ -0,0 +1,19 @@
1
+ { src, workspace_root }:
2
+ {
3
+ inherit src workspace_root;
4
+ root_path = "develops/fluidattacks-core/python/models";
5
+ module_name = "fluidattacks_core";
6
+ pypi_token = {
7
+ method = "oidc";
8
+ };
9
+ override = {
10
+ checks = {
11
+ basedpyright = false;
12
+ };
13
+ configs = {
14
+ import_linter = ../import-linter.cfg;
15
+ mypy = ../mypy.ini;
16
+ ruff = ../ruff.toml;
17
+ };
18
+ };
19
+ }
@@ -0,0 +1,13 @@
1
+ path_filter: src:
2
+ path_filter {
3
+ root = src;
4
+ include = [
5
+ "fluidattacks_core"
6
+ "tests"
7
+ "import-linter.cfg"
8
+ "mypy.ini"
9
+ "pyproject.toml"
10
+ "ruff.toml"
11
+ "uv.lock"
12
+ ];
13
+ }
@@ -0,0 +1,303 @@
1
+ {
2
+ "nodes": {
3
+ "flake-parts": {
4
+ "inputs": {
5
+ "nixpkgs-lib": "nixpkgs-lib"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1762810396,
9
+ "narHash": "sha256-dxFVgQPG+R72dkhXTtqUm7KpxElw3u6E+YlQ2WaDgt8=",
10
+ "owner": "hercules-ci",
11
+ "repo": "flake-parts",
12
+ "rev": "0bdadb1b265fb4143a75bd1ec7d8c915898a9923",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "hercules-ci",
17
+ "repo": "flake-parts",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nix_filter": {
22
+ "locked": {
23
+ "lastModified": 1757882181,
24
+ "narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=",
25
+ "owner": "numtide",
26
+ "repo": "nix-filter",
27
+ "rev": "59c44d1909c72441144b93cf0f054be7fe764de5",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "numtide",
32
+ "repo": "nix-filter",
33
+ "type": "github"
34
+ }
35
+ },
36
+ "nixpkgs": {
37
+ "locked": {
38
+ "lastModified": 1758690382,
39
+ "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
40
+ "owner": "nixos",
41
+ "repo": "nixpkgs",
42
+ "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
43
+ "type": "github"
44
+ },
45
+ "original": {
46
+ "owner": "nixos",
47
+ "ref": "nixos-unstable",
48
+ "repo": "nixpkgs",
49
+ "type": "github"
50
+ }
51
+ },
52
+ "nixpkgs-lib": {
53
+ "locked": {
54
+ "lastModified": 1761765539,
55
+ "narHash": "sha256-b0yj6kfvO8ApcSE+QmA6mUfu8IYG6/uU28OFn4PaC8M=",
56
+ "owner": "nix-community",
57
+ "repo": "nixpkgs.lib",
58
+ "rev": "719359f4562934ae99f5443f20aa06c2ffff91fc",
59
+ "type": "github"
60
+ },
61
+ "original": {
62
+ "owner": "nix-community",
63
+ "repo": "nixpkgs.lib",
64
+ "type": "github"
65
+ }
66
+ },
67
+ "nixpkgs_2": {
68
+ "locked": {
69
+ "lastModified": 1758690382,
70
+ "narHash": "sha256-NY3kSorgqE5LMm1LqNwGne3ZLMF2/ILgLpFr1fS4X3o=",
71
+ "owner": "nixos",
72
+ "repo": "nixpkgs",
73
+ "rev": "e643668fd71b949c53f8626614b21ff71a07379d",
74
+ "type": "github"
75
+ },
76
+ "original": {
77
+ "owner": "nixos",
78
+ "ref": "nixos-unstable",
79
+ "repo": "nixpkgs",
80
+ "type": "github"
81
+ }
82
+ },
83
+ "nixpkgs_3": {
84
+ "locked": {
85
+ "lastModified": 1761373498,
86
+ "narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=",
87
+ "owner": "nixos",
88
+ "repo": "nixpkgs",
89
+ "rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce",
90
+ "type": "github"
91
+ },
92
+ "original": {
93
+ "owner": "nixos",
94
+ "ref": "nixos-unstable",
95
+ "repo": "nixpkgs",
96
+ "type": "github"
97
+ }
98
+ },
99
+ "nixpkgs_flake": {
100
+ "locked": {
101
+ "lastModified": 1778253243,
102
+ "narHash": "sha256-KkH2QvU6iRLDTGGEwH5jnMqHWj4zMTuHxi1S1zdr01w=",
103
+ "owner": "nixos",
104
+ "repo": "nixpkgs",
105
+ "rev": "4fcda7103530b23c5ca44286344912082aad4220",
106
+ "type": "github"
107
+ },
108
+ "original": {
109
+ "owner": "nixos",
110
+ "repo": "nixpkgs",
111
+ "type": "github"
112
+ }
113
+ },
114
+ "pyproject-build-systems": {
115
+ "inputs": {
116
+ "nixpkgs": "nixpkgs",
117
+ "pyproject-nix": "pyproject-nix",
118
+ "uv2nix": "uv2nix"
119
+ },
120
+ "locked": {
121
+ "lastModified": 1761781027,
122
+ "narHash": "sha256-YDvxPAm2WnxrznRqWwHLjryBGG5Ey1ATEJXrON+TWt8=",
123
+ "owner": "pyproject-nix",
124
+ "repo": "build-system-pkgs",
125
+ "rev": "795a980d25301e5133eca37adae37283ec3c8e66",
126
+ "type": "github"
127
+ },
128
+ "original": {
129
+ "owner": "pyproject-nix",
130
+ "repo": "build-system-pkgs",
131
+ "type": "github"
132
+ }
133
+ },
134
+ "pyproject-nix": {
135
+ "inputs": {
136
+ "nixpkgs": [
137
+ "python_builder",
138
+ "pyproject-build-systems",
139
+ "nixpkgs"
140
+ ]
141
+ },
142
+ "locked": {
143
+ "lastModified": 1758265079,
144
+ "narHash": "sha256-amLaLNwKSZPShQHzfgmc/9o76dU8xzN0743dWgvYlr8=",
145
+ "owner": "nix-community",
146
+ "repo": "pyproject.nix",
147
+ "rev": "02e9418fd4af638447dca4b17b1280da95527fc9",
148
+ "type": "github"
149
+ },
150
+ "original": {
151
+ "owner": "nix-community",
152
+ "repo": "pyproject.nix",
153
+ "type": "github"
154
+ }
155
+ },
156
+ "pyproject-nix_2": {
157
+ "inputs": {
158
+ "nixpkgs": "nixpkgs_2"
159
+ },
160
+ "locked": {
161
+ "lastModified": 1762427963,
162
+ "narHash": "sha256-CkPlAbIQ87wmjy5qHibfzk4DmMGBNqFer+lLfXjpP5M=",
163
+ "owner": "pyproject-nix",
164
+ "repo": "pyproject.nix",
165
+ "rev": "4540ea004e04fcd12dd2738d51383d10f956f7b9",
166
+ "type": "github"
167
+ },
168
+ "original": {
169
+ "owner": "pyproject-nix",
170
+ "repo": "pyproject.nix",
171
+ "type": "github"
172
+ }
173
+ },
174
+ "pyproject-nix_3": {
175
+ "inputs": {
176
+ "nixpkgs": [
177
+ "python_builder",
178
+ "uv2nix",
179
+ "nixpkgs"
180
+ ]
181
+ },
182
+ "locked": {
183
+ "lastModified": 1760402624,
184
+ "narHash": "sha256-jF6UKLs2uGc2rtved8Vrt58oTWjTQoAssuYs/0578Z4=",
185
+ "owner": "pyproject-nix",
186
+ "repo": "pyproject.nix",
187
+ "rev": "84c4ea102127c77058ea1ed7be7300261fafc7d2",
188
+ "type": "github"
189
+ },
190
+ "original": {
191
+ "owner": "pyproject-nix",
192
+ "repo": "pyproject.nix",
193
+ "type": "github"
194
+ }
195
+ },
196
+ "python_builder": {
197
+ "inputs": {
198
+ "nix_filter": "nix_filter",
199
+ "nixpkgs_flake": "nixpkgs_flake",
200
+ "pyproject-build-systems": "pyproject-build-systems",
201
+ "pyproject-nix": "pyproject-nix_2",
202
+ "shell-helpers": "shell-helpers",
203
+ "uv2nix": "uv2nix_2"
204
+ },
205
+ "locked": {
206
+ "dir": "common/utils/python-builder",
207
+ "lastModified": 1787078362,
208
+ "narHash": "sha256-HYL7Rn6SuNjYxkt/PwFLksZjsauCiY+ENbOWryLsIlw=",
209
+ "ref": "refs/heads/trunk",
210
+ "rev": "09fd25a13309eb5e3b5b2a061bb340df3ae5d281",
211
+ "shallow": true,
212
+ "type": "git",
213
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
214
+ },
215
+ "original": {
216
+ "dir": "common/utils/python-builder",
217
+ "rev": "09fd25a13309eb5e3b5b2a061bb340df3ae5d281",
218
+ "shallow": true,
219
+ "type": "git",
220
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
221
+ }
222
+ },
223
+ "root": {
224
+ "inputs": {
225
+ "python_builder": "python_builder"
226
+ }
227
+ },
228
+ "shell-helpers": {
229
+ "inputs": {
230
+ "flake-parts": "flake-parts",
231
+ "nixpkgs": [
232
+ "python_builder",
233
+ "nixpkgs_flake"
234
+ ]
235
+ },
236
+ "locked": {
237
+ "dir": "common/utils/shell-helpers",
238
+ "lastModified": 1762806066,
239
+ "narHash": "sha256-Wz99Fl7SpPU1NkTHJ36XOo6DjOEAMXCw3ThRABOS2Hs=",
240
+ "ref": "refs/heads/trunk",
241
+ "rev": "d73cfdc7ae9e7f547e22a4481d4c2ccce38b26a8",
242
+ "shallow": true,
243
+ "type": "git",
244
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
245
+ },
246
+ "original": {
247
+ "dir": "common/utils/shell-helpers",
248
+ "rev": "d73cfdc7ae9e7f547e22a4481d4c2ccce38b26a8",
249
+ "shallow": true,
250
+ "type": "git",
251
+ "url": "ssh://git@gitlab.com/fluidattacks/universe"
252
+ }
253
+ },
254
+ "uv2nix": {
255
+ "inputs": {
256
+ "nixpkgs": [
257
+ "python_builder",
258
+ "pyproject-build-systems",
259
+ "nixpkgs"
260
+ ],
261
+ "pyproject-nix": [
262
+ "python_builder",
263
+ "pyproject-build-systems",
264
+ "pyproject-nix"
265
+ ]
266
+ },
267
+ "locked": {
268
+ "lastModified": 1758933732,
269
+ "narHash": "sha256-HAmm1GBS1myZCFuog0DC2ZLaynvZtiUI2Crmo+cdQI0=",
270
+ "owner": "pyproject-nix",
271
+ "repo": "uv2nix",
272
+ "rev": "273ce18f913d8559e0d04f820d724308966d7c4d",
273
+ "type": "github"
274
+ },
275
+ "original": {
276
+ "owner": "pyproject-nix",
277
+ "repo": "uv2nix",
278
+ "type": "github"
279
+ }
280
+ },
281
+ "uv2nix_2": {
282
+ "inputs": {
283
+ "nixpkgs": "nixpkgs_3",
284
+ "pyproject-nix": "pyproject-nix_3"
285
+ },
286
+ "locked": {
287
+ "lastModified": 1761872265,
288
+ "narHash": "sha256-i25GRgp2vUOebY70L3NTAgkd+Pr1hnn5xM3qHxH0ONU=",
289
+ "owner": "pyproject-nix",
290
+ "repo": "uv2nix",
291
+ "rev": "74dfb62871be152ad3673b143b0cc56105a4f3c5",
292
+ "type": "github"
293
+ },
294
+ "original": {
295
+ "owner": "pyproject-nix",
296
+ "repo": "uv2nix",
297
+ "type": "github"
298
+ }
299
+ }
300
+ },
301
+ "root": "root",
302
+ "version": 7
303
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ description = "Fluid Attacks Core models package.";
3
+
4
+ inputs = {
5
+ python_builder = {
6
+ url = "git+ssh://git@gitlab.com/fluidattacks/universe?shallow=1&rev=09fd25a13309eb5e3b5b2a061bb340df3ae5d281&dir=common/utils/python-builder";
7
+ };
8
+ };
9
+
10
+ outputs =
11
+ { self, ... }@inputs:
12
+ let
13
+ build_args =
14
+ {
15
+ system,
16
+ python_version,
17
+ nixpkgs,
18
+ builders,
19
+ scripts,
20
+ }:
21
+ import ./build {
22
+ src = import ./build/filter.nix nixpkgs.nix-filter self;
23
+ workspace_root = ./.;
24
+ };
25
+ in
26
+ {
27
+ packages = inputs.python_builder.outputs.build build_args;
28
+ };
29
+ }
@@ -0,0 +1,67 @@
1
+ from fluidattacks_core.models.scanners.apk_config import ApkConfig, ApkEnvironment
2
+ from fluidattacks_core.models.scanners.common_config import (
3
+ FalsePositivesConfig,
4
+ LocalesEnum,
5
+ OutputConfig,
6
+ OutputFormat,
7
+ )
8
+ from fluidattacks_core.models.scanners.containers_sca_config import (
9
+ ContainerImageConfig,
10
+ ContainerScaItem,
11
+ ContainersScaConfig,
12
+ DockerCredentialsConfig,
13
+ EcrCredentialsConfig,
14
+ )
15
+ from fluidattacks_core.models.scanners.cspm_config import AwsCredentials, AwsRole, CspmConfig
16
+ from fluidattacks_core.models.scanners.dast_config import (
17
+ DastApiAuth,
18
+ DastApiConfig,
19
+ DastConfig,
20
+ DastUrl,
21
+ )
22
+ from fluidattacks_core.models.scanners.loader import build_config, load_yaml_mapping
23
+ from fluidattacks_core.models.scanners.sast_config import SastConfig
24
+ from fluidattacks_core.models.scanners.sbom_config import (
25
+ SbomAwsCredentials,
26
+ SbomConfig,
27
+ SbomDockerCredentials,
28
+ SbomOutputConfig,
29
+ SbomPlatformOverrides,
30
+ SourceType,
31
+ )
32
+ from fluidattacks_core.models.scanners.sca_config import ScaConfig
33
+ from fluidattacks_core.models.scanners.scan_config import ScanConfig
34
+ from fluidattacks_core.models.scanners.sniffs_config import SniffsConfig
35
+
36
+ __all__ = [
37
+ "ApkConfig",
38
+ "ApkEnvironment",
39
+ "AwsCredentials",
40
+ "AwsRole",
41
+ "ContainerImageConfig",
42
+ "ContainerScaItem",
43
+ "ContainersScaConfig",
44
+ "CspmConfig",
45
+ "DastApiAuth",
46
+ "DastApiConfig",
47
+ "DastConfig",
48
+ "DastUrl",
49
+ "DockerCredentialsConfig",
50
+ "EcrCredentialsConfig",
51
+ "FalsePositivesConfig",
52
+ "LocalesEnum",
53
+ "OutputConfig",
54
+ "OutputFormat",
55
+ "SastConfig",
56
+ "SbomAwsCredentials",
57
+ "SbomConfig",
58
+ "SbomDockerCredentials",
59
+ "SbomOutputConfig",
60
+ "SbomPlatformOverrides",
61
+ "ScaConfig",
62
+ "ScanConfig",
63
+ "SniffsConfig",
64
+ "SourceType",
65
+ "build_config",
66
+ "load_yaml_mapping",
67
+ ]
@@ -0,0 +1,26 @@
1
+ from pydantic import BaseModel, StrictBool
2
+
3
+
4
+ class ApkEnvironment(BaseModel):
5
+ model_config = {"extra": "forbid"}
6
+ apk_file_path: str
7
+ environment_id: str | None = None
8
+
9
+ def __eq__(self, other: object) -> bool:
10
+ """Compare only on apk_file_path, ignoring environment_id."""
11
+ if not isinstance(other, ApkEnvironment):
12
+ return NotImplemented
13
+ return self.apk_file_path == other.apk_file_path
14
+
15
+ def __hash__(self) -> int:
16
+ """Hash only on apk_file_path, ignoring environment_id."""
17
+ return hash(self.apk_file_path)
18
+
19
+
20
+ class ApkConfig(BaseModel):
21
+ model_config = {"extra": "forbid"}
22
+ include: list[str] = []
23
+ exclude: list[str] = []
24
+ use_sast_analysis: StrictBool = True
25
+ environments: list[ApkEnvironment] | None = None
26
+ feature_preview: StrictBool | None = None
@@ -0,0 +1,27 @@
1
+ from enum import Enum
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class LocalesEnum(Enum):
7
+ EN = "EN"
8
+ ES = "ES"
9
+
10
+
11
+ class OutputFormat(Enum):
12
+ CSV = "CSV"
13
+ SARIF = "SARIF"
14
+ ALL = "ALL"
15
+
16
+
17
+ class OutputConfig(BaseModel):
18
+ model_config = {"extra": "forbid"}
19
+ file_path: str
20
+ format: OutputFormat
21
+
22
+
23
+ class FalsePositivesConfig(BaseModel):
24
+ model_config = {"extra": "forbid"}
25
+ findings: list[str] = []
26
+ method_names: list[str] = []
27
+ cve: list[str] = []
@@ -0,0 +1,37 @@
1
+ from pydantic import BaseModel, StrictBool
2
+
3
+
4
+ class EcrCredentialsConfig(BaseModel):
5
+ model_config = {"extra": "allow"}
6
+ access_key_id: str | None = None
7
+ secret_access_key: str | None = None
8
+ session_token: str | None = None
9
+ role_arn: str | None = None
10
+ external_id: str | None = None
11
+ aws_region: str | None = None
12
+
13
+
14
+ class DockerCredentialsConfig(BaseModel):
15
+ model_config = {"extra": "allow"}
16
+ docker_username: str
17
+ docker_password: str
18
+
19
+
20
+ class ContainerImageConfig(BaseModel):
21
+ model_config = {"extra": "allow"}
22
+ use_docker_daemon: StrictBool | None = None
23
+ os_override: str | None = None
24
+ arch_override: str | None = None
25
+ ecr_credentials: EcrCredentialsConfig | None = None
26
+ docker_credentials: DockerCredentialsConfig | None = None
27
+
28
+
29
+ class ContainerScaItem(BaseModel):
30
+ model_config = {"extra": "allow"}
31
+ image_uri: str
32
+ image_config: ContainerImageConfig | None = None
33
+
34
+
35
+ class ContainersScaConfig(BaseModel):
36
+ model_config = {"extra": "allow"}
37
+ images: list[ContainerScaItem]
@@ -0,0 +1,45 @@
1
+ from pydantic import BaseModel, Field, StrictBool, field_validator, model_validator
2
+
3
+ from fluidattacks_core.models.scanners.loader import LoaderValidationInfo, resolve_env_var
4
+
5
+
6
+ class AwsCredentials(BaseModel):
7
+ model_config = {"extra": "forbid"}
8
+ access_key_id: str
9
+ secret_access_key: str
10
+ session_token: str | None = None
11
+ environment_id: str | None = None
12
+
13
+ @field_validator("access_key_id", "secret_access_key", "session_token", mode="before")
14
+ @classmethod
15
+ def _resolve_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
16
+ return resolve_env_var(v, info)
17
+
18
+ @model_validator(mode="after")
19
+ def _validate_key_session_token_pairing(self) -> "AwsCredentials":
20
+ is_temporary = self.access_key_id.startswith("ASIA")
21
+ if is_temporary and not self.session_token:
22
+ msg = "Temporary credentials (ASIA key) require a session_token"
23
+ raise ValueError(msg)
24
+ if not is_temporary and self.session_token:
25
+ msg = "Static credentials (AKIA key) must not include a session_token"
26
+ raise ValueError(msg)
27
+ return self
28
+
29
+
30
+ class AwsRole(BaseModel):
31
+ model_config = {"extra": "forbid"}
32
+ role: str = Field(repr=False)
33
+ external_id: str | None = Field(default=None, repr=False)
34
+ environment_id: str | None = None
35
+
36
+ @field_validator("role", "external_id", mode="before")
37
+ @classmethod
38
+ def _resolve_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
39
+ return resolve_env_var(v, info)
40
+
41
+
42
+ class CspmConfig(BaseModel):
43
+ model_config = {"extra": "forbid"}
44
+ aws_credentials: list[AwsCredentials | AwsRole] = []
45
+ feature_preview: StrictBool | None = None
@@ -0,0 +1,47 @@
1
+ from pydantic import BaseModel, StrictBool, field_validator
2
+
3
+ from fluidattacks_core.models.scanners.loader import LoaderValidationInfo, resolve_env_var
4
+
5
+
6
+ class DastUrl(BaseModel):
7
+ model_config = {"extra": "forbid"}
8
+ url: str
9
+ environment_id: str | None = None
10
+
11
+ def __eq__(self, other: object) -> bool:
12
+ """Compare only on url, ignoring environment_id."""
13
+ if not isinstance(other, DastUrl):
14
+ return NotImplemented
15
+ return self.url == other.url
16
+
17
+ def __hash__(self) -> int:
18
+ """Hash only on url, ignoring environment_id."""
19
+ return hash(self.url)
20
+
21
+
22
+ class DastApiAuth(BaseModel):
23
+ model_config = {"extra": "forbid"}
24
+ type: str
25
+ key: str
26
+ value: str
27
+
28
+ @field_validator("key", "value", mode="before")
29
+ @classmethod
30
+ def _resolve_credentials(cls, v: object, info: LoaderValidationInfo) -> object:
31
+ return resolve_env_var(v, info)
32
+
33
+
34
+ class DastApiConfig(BaseModel):
35
+ model_config = {"extra": "forbid"}
36
+ base_url: str
37
+ api_specs: list[str]
38
+ authentication: list[DastApiAuth] = []
39
+ environment_id: str | None = None
40
+
41
+
42
+ class DastConfig(BaseModel):
43
+ model_config = {"extra": "forbid"}
44
+ urls: list[DastUrl] = []
45
+ api: list[DastApiConfig] = []
46
+ feature_preview: StrictBool | None = None
47
+ strict_connectivity: StrictBool = False