fluidattacks_core_models 12.0.0__py3-none-any.whl

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.
File without changes
File without changes
@@ -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
@@ -0,0 +1,74 @@
1
+ import logging
2
+ import os
3
+ import re
4
+ from collections.abc import Mapping
5
+ from pathlib import Path
6
+ from typing import TypeVar, cast
7
+
8
+ import yaml
9
+ from pydantic import BaseModel
10
+ from pydantic import ValidationInfo as _PydanticValidationInfo
11
+
12
+ LoaderValidationInfo = _PydanticValidationInfo[dict[str, bool] | None]
13
+
14
+ T = TypeVar("T", bound=BaseModel)
15
+
16
+ LOGGER = logging.getLogger(__name__)
17
+
18
+ _ENV_PLACEHOLDER = re.compile(r"\$\{([A-Z_][A-Z0-9_]*)\}")
19
+
20
+
21
+ def _sub_env_var(m: re.Match[str]) -> str:
22
+ var_name = m.group(1)
23
+ value = os.environ.get(var_name)
24
+ if value is None:
25
+ LOGGER.warning("env var '%s' not set; substituting empty string", var_name)
26
+ return ""
27
+ LOGGER.info("env var '%s' set", var_name)
28
+ return value
29
+
30
+
31
+ def resolve_env_var(v: object, info: LoaderValidationInfo) -> object:
32
+ if not isinstance(v, str) or not (info.context or {}).get("resolve_env"):
33
+ return v
34
+ matches = list(_ENV_PLACEHOLDER.finditer(v))
35
+ if not matches:
36
+ return v
37
+ LOGGER.info("resolving %d placeholder(s) in field value", len(matches))
38
+ if len(matches) == 1 and matches[0].span() == (0, len(v)):
39
+ var_name = matches[0].group(1)
40
+ value = os.environ.get(var_name)
41
+ if value is None:
42
+ LOGGER.warning("env var '%s' not set; field will be None", var_name)
43
+ return None
44
+ LOGGER.info("env var '%s' set", var_name)
45
+ return value
46
+ return _ENV_PLACEHOLDER.sub(_sub_env_var, v)
47
+
48
+
49
+ def load_yaml_mapping(path: str) -> Mapping[str, object]:
50
+ file_path = Path(path)
51
+ with file_path.open(encoding="utf-8") as file:
52
+ data = cast("object", yaml.safe_load(file))
53
+
54
+ if data is None:
55
+ return {}
56
+
57
+ if not isinstance(data, Mapping):
58
+ msg = "YAML root must be a mapping"
59
+ raise TypeError(msg)
60
+
61
+ return data
62
+
63
+
64
+ def build_config(path: str, model_class: type[T]) -> T:
65
+ raw_data = load_yaml_mapping(path)
66
+ config = model_class.model_validate(raw_data, context={"resolve_env": True})
67
+ extras = cast("Mapping[str, object] | None", config.model_extra)
68
+ if extras:
69
+ LOGGER.warning(
70
+ "Some keys were not recognized: %s. "
71
+ "The analysis will be performed only using the supported keys",
72
+ ", ".join(sorted(extras)),
73
+ )
74
+ return config
@@ -0,0 +1,15 @@
1
+ from pydantic import BaseModel, StrictBool
2
+
3
+
4
+ class SastConfig(BaseModel):
5
+ model_config = {"extra": "forbid"}
6
+ include: list[str] | None = None
7
+ exclude: list[str] | None = None
8
+ recursion_limit: int | None = None
9
+ use_inspects: StrictBool | None = None
10
+ file_size_limit: StrictBool | None = None
11
+ multifile: StrictBool | None = None
12
+ use_report_soon: StrictBool | None = None
13
+ report_drafts: StrictBool | None = None
14
+ include_sniffs: StrictBool | None = None
15
+ feature_preview: str | None = None
@@ -0,0 +1,57 @@
1
+ from enum import Enum
2
+
3
+ from pydantic import BaseModel, StrictBool
4
+
5
+
6
+ class SourceType(Enum):
7
+ DIRECTORY = "dir"
8
+ DOCKER = "docker"
9
+ DOCKER_DAEMON = "docker-daemon"
10
+ ECR = "ecr"
11
+ ECR_WITH_CREDENTIALS = "ecr-with-credentials"
12
+
13
+
14
+ class SbomDockerCredentials(BaseModel):
15
+ model_config = {"extra": "forbid"}
16
+ username: str | None = None
17
+ password: str | None = None
18
+ use_docker_daemon: StrictBool | None = None
19
+
20
+
21
+ class SbomPlatformOverrides(BaseModel):
22
+ model_config = {"extra": "forbid"}
23
+ os_override: str | None = None
24
+ arch_override: str | None = None
25
+
26
+
27
+ class SbomAwsCredentials(BaseModel):
28
+ model_config = {"extra": "forbid"}
29
+ external_id: str | None = None
30
+ role: str | None = None
31
+ region: str | None = None
32
+ access_key_id: str | None = None
33
+ secret_access_key: str | None = None
34
+ session_token: str | None = None
35
+
36
+
37
+ class SbomOutputConfig(BaseModel):
38
+ model_config = {"extra": "forbid"}
39
+ name: str
40
+ format: str
41
+
42
+
43
+ class SbomConfig(BaseModel):
44
+ model_config = {"extra": "forbid"}
45
+ include: list[str] | None = None
46
+ exclude: list[str] | None = None
47
+ output: SbomOutputConfig | None = None
48
+ source: str | None = None
49
+ source_type: SourceType | None = None
50
+ image_uri: str | None = None
51
+ environment_id: str | None = None
52
+ docker_credentials: SbomDockerCredentials | None = None
53
+ platform_overrides: SbomPlatformOverrides | None = None
54
+ aws_credentials: SbomAwsCredentials | None = None
55
+ include_package_metadata: StrictBool | None = None
56
+ include_package_advisories: StrictBool | None = None
57
+ feature_preview: StrictBool | None = None
@@ -0,0 +1,16 @@
1
+ from pydantic import BaseModel, StrictBool
2
+
3
+
4
+ class ScaExclusion(BaseModel):
5
+ model_config = {"extra": "forbid"}
6
+ CVE: str
7
+ paths: list[str]
8
+
9
+
10
+ class ScaConfig(BaseModel):
11
+ model_config = {"extra": "forbid"}
12
+ include: list[str] | None = None
13
+ exclude: list[str] | None = None
14
+ use_spots_sca: StrictBool | None = None
15
+ feature_preview: StrictBool | None = None
16
+ exclusions: list[ScaExclusion] = []
@@ -0,0 +1,39 @@
1
+ from pydantic import BaseModel, StrictBool
2
+
3
+ from fluidattacks_core.models.scanners.apk_config import ApkConfig
4
+ from fluidattacks_core.models.scanners.common_config import (
5
+ FalsePositivesConfig,
6
+ LocalesEnum,
7
+ OutputConfig,
8
+ )
9
+ from fluidattacks_core.models.scanners.containers_sca_config import ContainersScaConfig
10
+ from fluidattacks_core.models.scanners.cspm_config import CspmConfig
11
+ from fluidattacks_core.models.scanners.dast_config import DastConfig
12
+ from fluidattacks_core.models.scanners.sast_config import SastConfig
13
+ from fluidattacks_core.models.scanners.sbom_config import SbomConfig
14
+ from fluidattacks_core.models.scanners.sca_config import ScaConfig
15
+ from fluidattacks_core.models.scanners.sniffs_config import SniffsConfig
16
+
17
+
18
+ class ScanConfig(BaseModel):
19
+ model_config = {"extra": "allow"}
20
+ working_dir: str | None = None
21
+ namespace: str | None = None
22
+ commit: str | None = None
23
+ language: LocalesEnum | None = None
24
+ execution_id: str | None = None
25
+ checks: list[str] | None = None
26
+ strict: StrictBool | None = None
27
+ strictness_threshold: str | None = None
28
+ tracing_opt_out: StrictBool | None = None
29
+ debug: StrictBool | None = None
30
+ output: OutputConfig | None = None
31
+ sast: SastConfig | None = None
32
+ sca: ScaConfig | None = None
33
+ containers_sca: ContainersScaConfig | None = None
34
+ sbom: SbomConfig | None = None
35
+ dast: DastConfig | None = None
36
+ cspm: CspmConfig | None = None
37
+ apk: ApkConfig | None = None
38
+ false_positives_identified: FalsePositivesConfig | None = None
39
+ ss: SniffsConfig | None = None
@@ -0,0 +1,9 @@
1
+ from pydantic import BaseModel, StrictBool
2
+
3
+
4
+ class SniffsConfig(BaseModel):
5
+ model_config = {"extra": "allow"}
6
+ include: list[str] | None = None
7
+ exclude: list[str] | None = None
8
+ min_entropy: float | None = None
9
+ feature_preview: StrictBool | None = None
@@ -0,0 +1,35 @@
1
+ from fluidattacks_core.models.state_machines.root_scanner import (
2
+ ContextualizesScanInput,
3
+ ContextualizesScanOptions,
4
+ PerRootScanOptions,
5
+ StateMachineExecutePerRootInput,
6
+ TJobNameSegment,
7
+ TracesScanInput,
8
+ TracesScanOptions,
9
+ TStorageKey,
10
+ )
11
+ from fluidattacks_core.models.state_machines.types import (
12
+ StateMachine,
13
+ StateMachineCloningInput,
14
+ StateMachineExecuteScannerInput,
15
+ StateMachineExecuteSiftsInput,
16
+ StateMachineRequestSbomMailInput,
17
+ TCloningTrigger,
18
+ )
19
+
20
+ __all__ = [
21
+ "ContextualizesScanInput",
22
+ "ContextualizesScanOptions",
23
+ "PerRootScanOptions",
24
+ "StateMachine",
25
+ "StateMachineCloningInput",
26
+ "StateMachineExecutePerRootInput",
27
+ "StateMachineExecuteScannerInput",
28
+ "StateMachineExecuteSiftsInput",
29
+ "StateMachineRequestSbomMailInput",
30
+ "TCloningTrigger",
31
+ "TJobNameSegment",
32
+ "TStorageKey",
33
+ "TracesScanInput",
34
+ "TracesScanOptions",
35
+ ]
@@ -0,0 +1,105 @@
1
+ import re
2
+ from hashlib import sha256
3
+ from typing import Annotated, Generic, TypeVar
4
+
5
+ from pydantic import (
6
+ AfterValidator,
7
+ BaseModel,
8
+ ConfigDict,
9
+ Field,
10
+ StringConstraints,
11
+ computed_field,
12
+ )
13
+
14
+ MACHINE_NAME_DIGEST_LENGTH = 18
15
+ MAX_EXECUTION_NAME = 80
16
+
17
+ STORAGE_KEY_PATTERN = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.-]*\Z")
18
+ UNSAFE_NAME_CHARS = re.compile(r"[^A-Za-z0-9_-]")
19
+
20
+
21
+ def _ensure_storage_key(value: str) -> str:
22
+ if not STORAGE_KEY_PATTERN.fullmatch(value) or ".." in value:
23
+ msg = f"invalid storage key: {value!r}"
24
+ raise ValueError(msg)
25
+ return value
26
+
27
+
28
+ TStorageKey = Annotated[str, AfterValidator(_ensure_storage_key)]
29
+ TVisibleAscii = Annotated[str, StringConstraints(pattern=r"^[!-~]+$")]
30
+ TJobNameSegment = Annotated[
31
+ str, StringConstraints(min_length=1, pattern=r"^[A-Za-z0-9][A-Za-z0-9_-]*$")
32
+ ]
33
+
34
+
35
+ class PerRootScanOptions(BaseModel):
36
+ model_config = ConfigDict(extra="forbid", frozen=True, revalidate_instances="always")
37
+ config_id: TStorageKey
38
+ group_name: TStorageKey
39
+ root_nickname: TStorageKey
40
+ user_email: TVisibleAscii = Field(..., min_length=1)
41
+
42
+
43
+ class ContextualizesScanOptions(PerRootScanOptions):
44
+ pass
45
+
46
+
47
+ class TracesScanOptions(PerRootScanOptions):
48
+ root_id: TStorageKey
49
+ commit: Annotated[str, StringConstraints(pattern=r"^[0-9a-f]{40}$")]
50
+
51
+
52
+ TOptions = TypeVar("TOptions", bound=PerRootScanOptions)
53
+
54
+
55
+ class StateMachineExecutePerRootInput(BaseModel, Generic[TOptions]):
56
+ model_config = ConfigDict(extra="forbid", frozen=True, serialize_by_alias=True)
57
+ job_definition: str = Field(..., min_length=1, serialization_alias="jobDefinition")
58
+ job_queue: str = Field(..., min_length=1, serialization_alias="jobQueue")
59
+ scanner_name: TJobNameSegment = Field(..., serialization_alias="scannerName")
60
+ options: TOptions = Field(..., exclude=True)
61
+
62
+ @computed_field(alias="configId") # type: ignore[prop-decorator]
63
+ @property
64
+ def config_id(self) -> str:
65
+ return self.options.config_id
66
+
67
+ @computed_field(alias="groupName") # type: ignore[prop-decorator]
68
+ @property
69
+ def group_name(self) -> str:
70
+ return self.options.group_name
71
+
72
+ @computed_field(alias="rootNickname") # type: ignore[prop-decorator]
73
+ @property
74
+ def root_nickname(self) -> str:
75
+ return self.options.root_nickname
76
+
77
+ @computed_field(alias="executionOptions") # type: ignore[prop-decorator]
78
+ @property
79
+ def execution_options(self) -> str:
80
+ return self.options.model_dump_json()
81
+
82
+ def to_wire(self) -> dict[str, str]:
83
+ return self.model_dump(mode="json", by_alias=True)
84
+
85
+ def get_machine_name(self) -> str:
86
+ digest = sha256(
87
+ (
88
+ f"{self.options.group_name}\x00{self.options.root_nickname}"
89
+ f"\x00{self.scanner_name}\x00{self.options.config_id}"
90
+ ).encode()
91
+ ).hexdigest()[:MACHINE_NAME_DIGEST_LENGTH]
92
+ readable = UNSAFE_NAME_CHARS.sub(
93
+ "_",
94
+ f"{self.options.group_name}_{self.options.root_nickname}_{self.scanner_name}",
95
+ )
96
+ budget = MAX_EXECUTION_NAME - MACHINE_NAME_DIGEST_LENGTH - 1
97
+ return f"{readable[:budget]}_{digest}"
98
+
99
+
100
+ class ContextualizesScanInput(StateMachineExecutePerRootInput[ContextualizesScanOptions]):
101
+ pass
102
+
103
+
104
+ class TracesScanInput(StateMachineExecutePerRootInput[TracesScanOptions]):
105
+ pass
@@ -0,0 +1,99 @@
1
+ from datetime import datetime
2
+ from functools import cached_property
3
+ from typing import Literal, NamedTuple
4
+ from uuid import uuid4
5
+
6
+ from pydantic import BaseModel, Field, computed_field
7
+
8
+ TCloningTrigger = Literal[
9
+ "clone_with_warp_scheduler",
10
+ "clone_no_special_network",
11
+ "root_activation",
12
+ "upload_git_root_file_mutation",
13
+ "add_git_root_mutation",
14
+ "migration",
15
+ "update_git_root_mutation",
16
+ "execute_machine_flow",
17
+ "sync_git_root_mutation",
18
+ "update_group_mutation",
19
+ "update_group_managed_mutation",
20
+ "reattack",
21
+ "clone_roots_that_have_not_cloned",
22
+ "re_queue_reattacks_scheduler",
23
+ ]
24
+
25
+
26
+ class StateMachine(NamedTuple):
27
+ arn: str
28
+ name: str
29
+ creation_date: datetime
30
+
31
+
32
+ class StateMachineCloningInput(BaseModel):
33
+ model_config = {"extra": "forbid"}
34
+ group_name: str = Field(..., serialization_alias="groupName")
35
+ network_name: str | None = Field(default=None, serialization_alias="networkName")
36
+ roots: list[str] = Field(..., serialization_alias="roots")
37
+ user_email: str = Field(..., serialization_alias="userEmail")
38
+ trigger: TCloningTrigger = Field(serialization_alias="trigger")
39
+ execute_sifts: bool = Field(..., serialization_alias="executeSifts")
40
+ cloning_job_queue: str = Field(
41
+ default="integrates_clone", serialization_alias="cloningJobQueue"
42
+ )
43
+
44
+ @computed_field(alias="configId") # type: ignore[prop-decorator]
45
+ @cached_property
46
+ def config_id(self) -> str:
47
+ return str(uuid4().time)
48
+
49
+ def get_machine_name(self) -> str:
50
+ return f"{self.group_name}_{self.trigger}-{self.config_id}"
51
+
52
+
53
+ class StateMachineExecuteScannerInput(BaseModel):
54
+ model_config = {"extra": "forbid"}
55
+ config_id: str = Field(
56
+ default_factory=lambda: str(uuid4().time), serialization_alias="configId"
57
+ )
58
+ group_name: str = Field(..., serialization_alias="groupName")
59
+ image_refs: list[str] | None = Field(default=None, serialization_alias="imageRefs")
60
+ job_definition: str = Field(..., serialization_alias="jobDefinition")
61
+ job_queue: str = Field(..., serialization_alias="jobQueue")
62
+ job_origin: str = Field(..., serialization_alias="jobOrigin", exclude=True)
63
+ network_name: str | None = Field(default=None, serialization_alias="networkName")
64
+ roots: list[str] = Field(..., min_length=1, serialization_alias="roots")
65
+ scanner_name: str = Field(..., serialization_alias="scannerName")
66
+ user_email: str = Field(..., serialization_alias="userEmail")
67
+
68
+ def get_machine_name(self) -> str:
69
+ return f"{self.group_name}_{self.job_origin}_{self.scanner_name}_{self.config_id}"
70
+
71
+
72
+ class StateMachineExecuteSiftsInput(BaseModel):
73
+ model_config = {"extra": "forbid"}
74
+ config_id: str = Field(
75
+ default_factory=lambda: str(uuid4().time), serialization_alias="configId"
76
+ )
77
+ group_name: str = Field(..., serialization_alias="groupName")
78
+ root_nickname: str = Field(..., serialization_alias="rootNickname")
79
+ trigger: TCloningTrigger = Field(..., serialization_alias="trigger")
80
+ user_email: str = Field(..., serialization_alias="userEmail")
81
+
82
+ def get_machine_name(self) -> str:
83
+ return f"{self.group_name}_{self.trigger}_execute_sifts_{self.config_id}"
84
+
85
+
86
+ class StateMachineRequestSbomMailInput(BaseModel):
87
+ model_config = {"extra": "forbid"}
88
+ config_id: str = Field(
89
+ default_factory=lambda: str(uuid4().time), serialization_alias="configId"
90
+ )
91
+ group_name: str = Field(..., serialization_alias="groupName")
92
+ item_kind: Literal["root", "image"] = Field(..., serialization_alias="itemKind")
93
+ item_name: str = Field(..., serialization_alias="itemName")
94
+ notification_id: str = Field(..., serialization_alias="notificationId")
95
+ user_email: str = Field(..., serialization_alias="userEmail")
96
+ sbom_format: str = Field(..., serialization_alias="sbomFormat")
97
+
98
+ def get_machine_name(self) -> str:
99
+ return f"{self.group_name}_request_sbom_mail_{self.config_id}"
@@ -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,20 @@
1
+ fluidattacks_core/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ fluidattacks_core/models/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ fluidattacks_core/models/scanners/__init__.py,sha256=dsVrg8xfgSoqdfui5bHysLDITmpErDfJoB6K6kdhKYI,1873
4
+ fluidattacks_core/models/scanners/apk_config.py,sha256=KpR5DKXSO5-P8DMAbOhMnyWwb92Uxdv_XYBGYTErRE8,839
5
+ fluidattacks_core/models/scanners/common_config.py,sha256=YvlaE2ClSSnVD5UFMVWeu5eiMR70GMIzyDvG2oekeRI,471
6
+ fluidattacks_core/models/scanners/containers_sca_config.py,sha256=vSXHwck7IzcP2jNBm4IB3TClcVriS-r9mEVCMsigVQU,1047
7
+ fluidattacks_core/models/scanners/cspm_config.py,sha256=CFG-LVjlbPBSdpCpXtZdYs0oEJu2FOGDHF0fXLdvdZc,1703
8
+ fluidattacks_core/models/scanners/dast_config.py,sha256=cGZnYcJGWEFdV0g_RNl-HKwDhPyIHYO2PlMg2eOim7I,1336
9
+ fluidattacks_core/models/scanners/loader.py,sha256=l9kOUbDlCv-0R3LmJbOkwoXGUC7qNE4dEWiBZPVllr8,2297
10
+ fluidattacks_core/models/scanners/sast_config.py,sha256=iWy9icaE3UGvfBWLF5GMWBtLxYLbc6wPvTF3Yph4vfA,529
11
+ fluidattacks_core/models/scanners/sbom_config.py,sha256=ZisA15KwVnT587qO9wDKTYXDmfl1elOqKoJTUDWgHes,1638
12
+ fluidattacks_core/models/scanners/sca_config.py,sha256=SWh5gLS803vr7_9hdO4-7Y3PDof8TitLBdPUa16Kt9g,422
13
+ fluidattacks_core/models/scanners/scan_config.py,sha256=OShUdsFAA31bmUh2cJcf9ODhmLMnakHQ7dliVbiyWbc,1583
14
+ fluidattacks_core/models/scanners/sniffs_config.py,sha256=mHebiayRToLn0EjT4xbxiwmEi-LNc6VpuhQnUzoqtE4,271
15
+ fluidattacks_core/models/state_machines/__init__.py,sha256=wSsH_I1Y-Md-Ele3EftdwbdA7HBl8VG1JwyC5_REQEY,938
16
+ fluidattacks_core/models/state_machines/root_scanner.py,sha256=FQZk7-zuE1D12GjFHLERpIW3Idd3fkLhq6pmFPDvKbo,3365
17
+ fluidattacks_core/models/state_machines/types.py,sha256=5wPuLTEjapYvQg9DYAgmo2BaDxZQl1ZKMtiKX_izkJo,3967
18
+ fluidattacks_core_models-12.0.0.dist-info/METADATA,sha256=k3KybJsmyKRQ7ZaBuDtbgLBMVMFQl4LlSTyvO6IAC0E,592
19
+ fluidattacks_core_models-12.0.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
20
+ fluidattacks_core_models-12.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any