diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index f731f36b79..a6ab1a8fef 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -41365,6 +41365,7 @@ components: example: CloudTrail Account Change oneOf: - $ref: '#/components/schemas/ObservabilityPipelineOcsfMappingLibrary' + - $ref: '#/components/schemas/ObservabilityPipelineOcsfMappingCustom' ObservabilityPipelineOcsfMapperProcessorType: default: ocsf_mapper description: The processor type. The value should always be `ocsf_mapper`. @@ -41374,6 +41375,116 @@ components: type: string x-enum-varnames: - OCSF_MAPPER + ObservabilityPipelineOcsfMappingCustom: + description: Custom OCSF mapping configuration for transforming logs. + properties: + mapping: + description: A list of field mapping rules for transforming log fields to + OCSF schema fields. + items: + $ref: '#/components/schemas/ObservabilityPipelineOcsfMappingCustomFieldMapping' + type: array + metadata: + $ref: '#/components/schemas/ObservabilityPipelineOcsfMappingCustomMetadata' + version: + description: The version of the custom mapping configuration. + example: 1 + format: int64 + type: integer + required: + - mapping + - metadata + - version + type: object + ObservabilityPipelineOcsfMappingCustomFieldMapping: + description: Defines a single field mapping rule for transforming a source field + to an OCSF destination field. + properties: + default: + description: The default value to use if the source field is missing or + empty. + example: '' + dest: + description: The destination OCSF field path. + example: device.type + type: string + lookup: + $ref: '#/components/schemas/ObservabilityPipelineOcsfMappingCustomLookup' + source: + description: The source field path from the log event. + example: host.type + sources: + description: Multiple source field paths for combined mapping. + example: + - field1 + - field2 + value: + description: A static value to use for the destination field. + example: static_value + required: + - dest + type: object + ObservabilityPipelineOcsfMappingCustomLookup: + description: Lookup table configuration for mapping source values to destination + values. + properties: + default: + description: The default value to use if no lookup match is found. + example: unknown + table: + description: A list of lookup table entries for value transformation. + items: + $ref: '#/components/schemas/ObservabilityPipelineOcsfMappingCustomLookupTableEntry' + type: array + type: object + ObservabilityPipelineOcsfMappingCustomLookupTableEntry: + description: A single entry in a lookup table for value transformation. + properties: + contains: + description: The substring to match in the source value. + example: Desktop + type: string + equals: + description: The exact value to match in the source. + example: desktop + equals_source: + description: The source field to match against. + example: device_type + type: string + matches: + description: A regex pattern to match in the source value. + example: ^Desktop.* + type: string + not_matches: + description: A regex pattern that must not match the source value. + example: ^Mobile.* + type: string + value: + description: The value to use when a match is found. + example: desktop + type: object + ObservabilityPipelineOcsfMappingCustomMetadata: + description: Metadata for the custom OCSF mapping. + properties: + class: + description: The OCSF event class name. + example: Device Inventory Info + type: string + profiles: + description: A list of OCSF profiles to apply. + example: + - container + items: + type: string + type: array + version: + description: The OCSF schema version. + example: 1.3.0 + type: string + required: + - class + - version + type: object ObservabilityPipelineOcsfMappingLibrary: description: Predefined library mappings for common log formats. enum: diff --git a/docs/datadog_api_client.v2.model.rst b/docs/datadog_api_client.v2.model.rst index 2650a2bc3c..eae942a5d4 100644 --- a/docs/datadog_api_client.v2.model.rst +++ b/docs/datadog_api_client.v2.model.rst @@ -17861,6 +17861,41 @@ datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapper\_processor\_ :members: :show-inheritance: +datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapping\_custom module +----------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapping\_custom\_field\_mapping module +--------------------------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_field_mapping + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapping\_custom\_lookup module +------------------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapping\_custom\_lookup\_table\_entry module +--------------------------------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup_table_entry + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapping\_custom\_metadata module +--------------------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_metadata + :members: + :show-inheritance: + datadog\_api\_client.v2.model.observability\_pipeline\_ocsf\_mapping\_library module ------------------------------------------------------------------------------------ diff --git a/examples/v2/observability-pipelines/ValidatePipeline_3024756866.py b/examples/v2/observability-pipelines/ValidatePipeline_3024756866.py new file mode 100644 index 0000000000..835241a8b6 --- /dev/null +++ b/examples/v2/observability-pipelines/ValidatePipeline_3024756866.py @@ -0,0 +1,140 @@ +""" +Validate an observability pipeline with OCSF mapper custom mapping returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.observability_pipelines_api import ObservabilityPipelinesApi +from datadog_api_client.v2.model.observability_pipeline_config import ObservabilityPipelineConfig +from datadog_api_client.v2.model.observability_pipeline_config_processor_group import ( + ObservabilityPipelineConfigProcessorGroup, +) +from datadog_api_client.v2.model.observability_pipeline_data_attributes import ObservabilityPipelineDataAttributes +from datadog_api_client.v2.model.observability_pipeline_datadog_agent_source import ( + ObservabilityPipelineDatadogAgentSource, +) +from datadog_api_client.v2.model.observability_pipeline_datadog_agent_source_type import ( + ObservabilityPipelineDatadogAgentSourceType, +) +from datadog_api_client.v2.model.observability_pipeline_datadog_logs_destination import ( + ObservabilityPipelineDatadogLogsDestination, +) +from datadog_api_client.v2.model.observability_pipeline_datadog_logs_destination_type import ( + ObservabilityPipelineDatadogLogsDestinationType, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor import ( + ObservabilityPipelineOcsfMapperProcessor, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor_mapping import ( + ObservabilityPipelineOcsfMapperProcessorMapping, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor_type import ( + ObservabilityPipelineOcsfMapperProcessorType, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom import ( + ObservabilityPipelineOcsfMappingCustom, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_field_mapping import ( + ObservabilityPipelineOcsfMappingCustomFieldMapping, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup import ( + ObservabilityPipelineOcsfMappingCustomLookup, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup_table_entry import ( + ObservabilityPipelineOcsfMappingCustomLookupTableEntry, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_metadata import ( + ObservabilityPipelineOcsfMappingCustomMetadata, +) +from datadog_api_client.v2.model.observability_pipeline_spec import ObservabilityPipelineSpec +from datadog_api_client.v2.model.observability_pipeline_spec_data import ObservabilityPipelineSpecData + +body = ObservabilityPipelineSpec( + data=ObservabilityPipelineSpecData( + attributes=ObservabilityPipelineDataAttributes( + config=ObservabilityPipelineConfig( + destinations=[ + ObservabilityPipelineDatadogLogsDestination( + id="datadog-logs-destination", + inputs=[ + "my-processor-group", + ], + type=ObservabilityPipelineDatadogLogsDestinationType.DATADOG_LOGS, + ), + ], + processor_groups=[ + ObservabilityPipelineConfigProcessorGroup( + enabled=True, + id="my-processor-group", + include="service:my-service", + inputs=[ + "datadog-agent-source", + ], + processors=[ + ObservabilityPipelineOcsfMapperProcessor( + enabled=True, + id="ocsf-mapper-processor", + include="service:my-service", + mappings=[ + ObservabilityPipelineOcsfMapperProcessorMapping( + include="source:custom", + mapping=ObservabilityPipelineOcsfMappingCustom( + mapping=[ + ObservabilityPipelineOcsfMappingCustomFieldMapping( + default="", + dest="time", + source="timestamp", + ), + ObservabilityPipelineOcsfMappingCustomFieldMapping( + default="", + dest="severity", + source="level", + ), + ObservabilityPipelineOcsfMappingCustomFieldMapping( + default="", + dest="device.type", + lookup=ObservabilityPipelineOcsfMappingCustomLookup( + table=[ + ObservabilityPipelineOcsfMappingCustomLookupTableEntry( + contains="Desktop", + value="desktop", + ), + ], + ), + source="host.type", + ), + ], + metadata=ObservabilityPipelineOcsfMappingCustomMetadata( + _class="Device Inventory Info", + profiles=[ + "container", + ], + version="1.3.0", + ), + version=1, + ), + ), + ], + type=ObservabilityPipelineOcsfMapperProcessorType.OCSF_MAPPER, + ), + ], + ), + ], + sources=[ + ObservabilityPipelineDatadogAgentSource( + id="datadog-agent-source", + type=ObservabilityPipelineDatadogAgentSourceType.DATADOG_AGENT, + ), + ], + ), + name="OCSF Custom Mapper Pipeline", + ), + type="pipelines", + ), +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = ObservabilityPipelinesApi(api_client) + response = api_instance.validate_pipeline(body=body) + + print(response) diff --git a/examples/v2/observability-pipelines/ValidatePipeline_3565101276.py b/examples/v2/observability-pipelines/ValidatePipeline_3565101276.py new file mode 100644 index 0000000000..2a97473285 --- /dev/null +++ b/examples/v2/observability-pipelines/ValidatePipeline_3565101276.py @@ -0,0 +1,91 @@ +""" +Validate an observability pipeline with OCSF mapper library mapping returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.observability_pipelines_api import ObservabilityPipelinesApi +from datadog_api_client.v2.model.observability_pipeline_config import ObservabilityPipelineConfig +from datadog_api_client.v2.model.observability_pipeline_config_processor_group import ( + ObservabilityPipelineConfigProcessorGroup, +) +from datadog_api_client.v2.model.observability_pipeline_data_attributes import ObservabilityPipelineDataAttributes +from datadog_api_client.v2.model.observability_pipeline_datadog_agent_source import ( + ObservabilityPipelineDatadogAgentSource, +) +from datadog_api_client.v2.model.observability_pipeline_datadog_agent_source_type import ( + ObservabilityPipelineDatadogAgentSourceType, +) +from datadog_api_client.v2.model.observability_pipeline_datadog_logs_destination import ( + ObservabilityPipelineDatadogLogsDestination, +) +from datadog_api_client.v2.model.observability_pipeline_datadog_logs_destination_type import ( + ObservabilityPipelineDatadogLogsDestinationType, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor import ( + ObservabilityPipelineOcsfMapperProcessor, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor_mapping import ( + ObservabilityPipelineOcsfMapperProcessorMapping, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor_type import ( + ObservabilityPipelineOcsfMapperProcessorType, +) +from datadog_api_client.v2.model.observability_pipeline_spec import ObservabilityPipelineSpec +from datadog_api_client.v2.model.observability_pipeline_spec_data import ObservabilityPipelineSpecData + +body = ObservabilityPipelineSpec( + data=ObservabilityPipelineSpecData( + attributes=ObservabilityPipelineDataAttributes( + config=ObservabilityPipelineConfig( + destinations=[ + ObservabilityPipelineDatadogLogsDestination( + id="datadog-logs-destination", + inputs=[ + "my-processor-group", + ], + type=ObservabilityPipelineDatadogLogsDestinationType.DATADOG_LOGS, + ), + ], + processor_groups=[ + ObservabilityPipelineConfigProcessorGroup( + enabled=True, + id="my-processor-group", + include="service:my-service", + inputs=[ + "datadog-agent-source", + ], + processors=[ + ObservabilityPipelineOcsfMapperProcessor( + enabled=True, + id="ocsf-mapper-processor", + include="service:my-service", + type=ObservabilityPipelineOcsfMapperProcessorType.OCSF_MAPPER, + mappings=[ + ObservabilityPipelineOcsfMapperProcessorMapping( + include="source:cloudtrail", + mapping="CloudTrail Account Change", + ), + ], + ), + ], + ), + ], + sources=[ + ObservabilityPipelineDatadogAgentSource( + id="datadog-agent-source", + type=ObservabilityPipelineDatadogAgentSourceType.DATADOG_AGENT, + ), + ], + ), + name="OCSF Mapper Pipeline", + ), + type="pipelines", + ), +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = ObservabilityPipelinesApi(api_client) + response = api_instance.validate_pipeline(body=body) + + print(response) diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping.py index aec241a988..b577a0c60b 100644 --- a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping.py +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping.py @@ -15,6 +15,9 @@ from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor_mapping_mapping import ( ObservabilityPipelineOcsfMapperProcessorMappingMapping, ) + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom import ( + ObservabilityPipelineOcsfMappingCustom, + ) class ObservabilityPipelineOcsfMapperProcessorMapping(ModelNormal): @@ -35,7 +38,12 @@ def openapi_types(_): } def __init__( - self_, include: str, mapping: Union[ObservabilityPipelineOcsfMapperProcessorMappingMapping, str], **kwargs + self_, + include: str, + mapping: Union[ + ObservabilityPipelineOcsfMapperProcessorMappingMapping, str, ObservabilityPipelineOcsfMappingCustom + ], + **kwargs, ): """ Defines how specific events are transformed to OCSF using a mapping configuration. diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping_mapping.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping_mapping.py index 680dd496f2..554324fd4c 100644 --- a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping_mapping.py +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapper_processor_mapping_mapping.py @@ -14,6 +14,15 @@ class ObservabilityPipelineOcsfMapperProcessorMappingMapping(ModelComposed): def __init__(self, **kwargs): """ Defines a single mapping rule for transforming logs into the OCSF schema. + + :param mapping: A list of field mapping rules for transforming log fields to OCSF schema fields. + :type mapping: [ObservabilityPipelineOcsfMappingCustomFieldMapping] + + :param metadata: Metadata for the custom OCSF mapping. + :type metadata: ObservabilityPipelineOcsfMappingCustomMetadata + + :param version: The version of the custom mapping configuration. + :type version: int """ super().__init__(kwargs) @@ -26,8 +35,13 @@ def _composed_schemas(_): # code would be run when this module is imported, and these composed # classes don't exist yet because their module has not finished # loading + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom import ( + ObservabilityPipelineOcsfMappingCustom, + ) + return { "oneOf": [ str, + ObservabilityPipelineOcsfMappingCustom, ], } diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom.py new file mode 100644 index 0000000000..f81e190a6a --- /dev/null +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom.py @@ -0,0 +1,68 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_field_mapping import ( + ObservabilityPipelineOcsfMappingCustomFieldMapping, + ) + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_metadata import ( + ObservabilityPipelineOcsfMappingCustomMetadata, + ) + + +class ObservabilityPipelineOcsfMappingCustom(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_field_mapping import ( + ObservabilityPipelineOcsfMappingCustomFieldMapping, + ) + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_metadata import ( + ObservabilityPipelineOcsfMappingCustomMetadata, + ) + + return { + "mapping": ([ObservabilityPipelineOcsfMappingCustomFieldMapping],), + "metadata": (ObservabilityPipelineOcsfMappingCustomMetadata,), + "version": (int,), + } + + attribute_map = { + "mapping": "mapping", + "metadata": "metadata", + "version": "version", + } + + def __init__( + self_, + mapping: List[ObservabilityPipelineOcsfMappingCustomFieldMapping], + metadata: ObservabilityPipelineOcsfMappingCustomMetadata, + version: int, + **kwargs, + ): + """ + Custom OCSF mapping configuration for transforming logs. + + :param mapping: A list of field mapping rules for transforming log fields to OCSF schema fields. + :type mapping: [ObservabilityPipelineOcsfMappingCustomFieldMapping] + + :param metadata: Metadata for the custom OCSF mapping. + :type metadata: ObservabilityPipelineOcsfMappingCustomMetadata + + :param version: The version of the custom mapping configuration. + :type version: int + """ + super().__init__(kwargs) + + self_.mapping = mapping + self_.metadata = metadata + self_.version = version diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_field_mapping.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_field_mapping.py new file mode 100644 index 0000000000..0347c8e019 --- /dev/null +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_field_mapping.py @@ -0,0 +1,138 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Any, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + date, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup import ( + ObservabilityPipelineOcsfMappingCustomLookup, + ) + + +class ObservabilityPipelineOcsfMappingCustomFieldMapping(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup import ( + ObservabilityPipelineOcsfMappingCustomLookup, + ) + + return { + "default": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + "dest": (str,), + "lookup": (ObservabilityPipelineOcsfMappingCustomLookup,), + "source": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + "sources": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + "value": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + } + + attribute_map = { + "default": "default", + "dest": "dest", + "lookup": "lookup", + "source": "source", + "sources": "sources", + "value": "value", + } + + def __init__( + self_, + dest: str, + default: Union[Any, UnsetType] = unset, + lookup: Union[ObservabilityPipelineOcsfMappingCustomLookup, UnsetType] = unset, + source: Union[Any, UnsetType] = unset, + sources: Union[Any, UnsetType] = unset, + value: Union[Any, UnsetType] = unset, + **kwargs, + ): + """ + Defines a single field mapping rule for transforming a source field to an OCSF destination field. + + :param default: The default value to use if the source field is missing or empty. + :type default: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + + :param dest: The destination OCSF field path. + :type dest: str + + :param lookup: Lookup table configuration for mapping source values to destination values. + :type lookup: ObservabilityPipelineOcsfMappingCustomLookup, optional + + :param source: The source field path from the log event. + :type source: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + + :param sources: Multiple source field paths for combined mapping. + :type sources: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + + :param value: A static value to use for the destination field. + :type value: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + """ + if default is not unset: + kwargs["default"] = default + if lookup is not unset: + kwargs["lookup"] = lookup + if source is not unset: + kwargs["source"] = source + if sources is not unset: + kwargs["sources"] = sources + if value is not unset: + kwargs["value"] = value + super().__init__(kwargs) + + self_.dest = dest diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_lookup.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_lookup.py new file mode 100644 index 0000000000..991bff148b --- /dev/null +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_lookup.py @@ -0,0 +1,73 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Any, List, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + date, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup_table_entry import ( + ObservabilityPipelineOcsfMappingCustomLookupTableEntry, + ) + + +class ObservabilityPipelineOcsfMappingCustomLookup(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup_table_entry import ( + ObservabilityPipelineOcsfMappingCustomLookupTableEntry, + ) + + return { + "default": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + "table": ([ObservabilityPipelineOcsfMappingCustomLookupTableEntry],), + } + + attribute_map = { + "default": "default", + "table": "table", + } + + def __init__( + self_, + default: Union[Any, UnsetType] = unset, + table: Union[List[ObservabilityPipelineOcsfMappingCustomLookupTableEntry], UnsetType] = unset, + **kwargs, + ): + """ + Lookup table configuration for mapping source values to destination values. + + :param default: The default value to use if no lookup match is found. + :type default: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + + :param table: A list of lookup table entries for value transformation. + :type table: [ObservabilityPipelineOcsfMappingCustomLookupTableEntry], optional + """ + if default is not unset: + kwargs["default"] = default + if table is not unset: + kwargs["table"] = table + super().__init__(kwargs) diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_lookup_table_entry.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_lookup_table_entry.py new file mode 100644 index 0000000000..da93933e89 --- /dev/null +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_lookup_table_entry.py @@ -0,0 +1,106 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Any, Union + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + date, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +class ObservabilityPipelineOcsfMappingCustomLookupTableEntry(ModelNormal): + @cached_property + def openapi_types(_): + return { + "contains": (str,), + "equals": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + "equals_source": (str,), + "matches": (str,), + "not_matches": (str,), + "value": ( + bool, + date, + datetime, + dict, + float, + int, + list, + str, + UUID, + none_type, + ), + } + + attribute_map = { + "contains": "contains", + "equals": "equals", + "equals_source": "equals_source", + "matches": "matches", + "not_matches": "not_matches", + "value": "value", + } + + def __init__( + self_, + contains: Union[str, UnsetType] = unset, + equals: Union[Any, UnsetType] = unset, + equals_source: Union[str, UnsetType] = unset, + matches: Union[str, UnsetType] = unset, + not_matches: Union[str, UnsetType] = unset, + value: Union[Any, UnsetType] = unset, + **kwargs, + ): + """ + A single entry in a lookup table for value transformation. + + :param contains: The substring to match in the source value. + :type contains: str, optional + + :param equals: The exact value to match in the source. + :type equals: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + + :param equals_source: The source field to match against. + :type equals_source: str, optional + + :param matches: A regex pattern to match in the source value. + :type matches: str, optional + + :param not_matches: A regex pattern that must not match the source value. + :type not_matches: str, optional + + :param value: The value to use when a match is found. + :type value: bool, date, datetime, dict, float, int, list, str, UUID, none_type, optional + """ + if contains is not unset: + kwargs["contains"] = contains + if equals is not unset: + kwargs["equals"] = equals + if equals_source is not unset: + kwargs["equals_source"] = equals_source + if matches is not unset: + kwargs["matches"] = matches + if not_matches is not unset: + kwargs["not_matches"] = not_matches + if value is not unset: + kwargs["value"] = value + super().__init__(kwargs) diff --git a/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_metadata.py b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_metadata.py new file mode 100644 index 0000000000..4198eea99a --- /dev/null +++ b/src/datadog_api_client/v2/model/observability_pipeline_ocsf_mapping_custom_metadata.py @@ -0,0 +1,49 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, Union + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + unset, + UnsetType, +) + + +class ObservabilityPipelineOcsfMappingCustomMetadata(ModelNormal): + @cached_property + def openapi_types(_): + return { + "_class": (str,), + "profiles": ([str],), + "version": (str,), + } + + attribute_map = { + "_class": "class", + "profiles": "profiles", + "version": "version", + } + + def __init__(self_, _class: str, version: str, profiles: Union[List[str], UnsetType] = unset, **kwargs): + """ + Metadata for the custom OCSF mapping. + + :param _class: The OCSF event class name. + :type _class: str + + :param profiles: A list of OCSF profiles to apply. + :type profiles: [str], optional + + :param version: The OCSF schema version. + :type version: str + """ + if profiles is not unset: + kwargs["profiles"] = profiles + super().__init__(kwargs) + + self_._class = _class + self_.version = version diff --git a/src/datadog_api_client/v2/models/__init__.py b/src/datadog_api_client/v2/models/__init__.py index 7128642248..9d1f285a9d 100644 --- a/src/datadog_api_client/v2/models/__init__.py +++ b/src/datadog_api_client/v2/models/__init__.py @@ -3543,6 +3543,21 @@ from datadog_api_client.v2.model.observability_pipeline_ocsf_mapper_processor_type import ( ObservabilityPipelineOcsfMapperProcessorType, ) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom import ( + ObservabilityPipelineOcsfMappingCustom, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_field_mapping import ( + ObservabilityPipelineOcsfMappingCustomFieldMapping, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup import ( + ObservabilityPipelineOcsfMappingCustomLookup, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_lookup_table_entry import ( + ObservabilityPipelineOcsfMappingCustomLookupTableEntry, +) +from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_custom_metadata import ( + ObservabilityPipelineOcsfMappingCustomMetadata, +) from datadog_api_client.v2.model.observability_pipeline_ocsf_mapping_library import ( ObservabilityPipelineOcsfMappingLibrary, ) @@ -8583,6 +8598,11 @@ "ObservabilityPipelineOcsfMapperProcessorMapping", "ObservabilityPipelineOcsfMapperProcessorMappingMapping", "ObservabilityPipelineOcsfMapperProcessorType", + "ObservabilityPipelineOcsfMappingCustom", + "ObservabilityPipelineOcsfMappingCustomFieldMapping", + "ObservabilityPipelineOcsfMappingCustomLookup", + "ObservabilityPipelineOcsfMappingCustomLookupTableEntry", + "ObservabilityPipelineOcsfMappingCustomMetadata", "ObservabilityPipelineOcsfMappingLibrary", "ObservabilityPipelineOpenSearchDestination", "ObservabilityPipelineOpenSearchDestinationDataStream", diff --git a/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_custom_mapping_returns_ok_response.frozen b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_custom_mapping_returns_ok_response.frozen new file mode 100644 index 0000000000..0a0ae84b13 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_custom_mapping_returns_ok_response.frozen @@ -0,0 +1 @@ +2026-02-10T14:12:05.668Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_custom_mapping_returns_ok_response.yaml b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_custom_mapping_returns_ok_response.yaml new file mode 100644 index 0000000000..da06907dec --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_custom_mapping_returns_ok_response.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: '{"data":{"attributes":{"config":{"destinations":[{"id":"datadog-logs-destination","inputs":["my-processor-group"],"type":"datadog_logs"}],"processor_groups":[{"enabled":true,"id":"my-processor-group","include":"service:my-service","inputs":["datadog-agent-source"],"processors":[{"enabled":true,"id":"ocsf-mapper-processor","include":"service:my-service","mappings":[{"include":"source:custom","mapping":{"mapping":[{"default":"","dest":"time","source":"timestamp"},{"default":"","dest":"severity","source":"level"},{"default":"","dest":"device.type","lookup":{"table":[{"contains":"Desktop","value":"desktop"}]},"source":"host.type"}],"metadata":{"class":"Device + Inventory Info","profiles":["container"],"version":"1.3.0"},"version":1}}],"type":"ocsf_mapper"}]}],"sources":[{"id":"datadog-agent-source","type":"datadog_agent"}]},"name":"OCSF + Custom Mapper Pipeline"},"type":"pipelines"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/obs-pipelines/pipelines/validate + response: + body: + string: '{"errors":[]} + + ' + headers: + content-type: + - application/vnd.api+json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_invalid_custom_mapping_returns_bad_request_response.frozen b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_invalid_custom_mapping_returns_bad_request_response.frozen new file mode 100644 index 0000000000..55487b67b2 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_invalid_custom_mapping_returns_bad_request_response.frozen @@ -0,0 +1 @@ +2026-02-10T14:12:06.064Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_invalid_custom_mapping_returns_bad_request_response.yaml b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_invalid_custom_mapping_returns_bad_request_response.yaml new file mode 100644 index 0000000000..bc47f5bbcb --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_invalid_custom_mapping_returns_bad_request_response.yaml @@ -0,0 +1,26 @@ +interactions: +- request: + body: '{"data":{"attributes":{"config":{"destinations":[{"id":"datadog-logs-destination","inputs":["my-processor-group"],"type":"datadog_logs"}],"processor_groups":[{"enabled":true,"id":"my-processor-group","include":"service:my-service","inputs":["datadog-agent-source"],"processors":[{"enabled":true,"id":"ocsf-mapper-processor","include":"service:my-service","mappings":[{"include":"source:custom","mapping":{"mapping":[{"dest":"time","source":"timestamp"}],"metadata":{"class":"Invalid + Class","profiles":["container"],"version":"1.3.0"},"version":0}}],"type":"ocsf_mapper"}]}],"sources":[{"id":"datadog-agent-source","type":"datadog_agent"}]},"name":"OCSF + Invalid Mapper Pipeline"},"type":"pipelines"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/obs-pipelines/pipelines/validate + response: + body: + string: '{"errors":[{"title":"Schema version must be a positive integer","meta":{"field":"mappings.0.version","id":"ocsf-mapper-processor","message":"Schema + version must be a positive integer"}},{"title":"Invalid custom mapping class","meta":{"field":"mappings.0.metadata.class","id":"ocsf-mapper-processor","message":"Invalid + custom mapping class"}}]} + + ' + headers: + content-type: + - application/json + status: + code: 400 + message: Bad Request +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_library_mapping_returns_ok_response.frozen b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_library_mapping_returns_ok_response.frozen new file mode 100644 index 0000000000..fbeecac324 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_library_mapping_returns_ok_response.frozen @@ -0,0 +1 @@ +2026-02-10T14:12:05.285Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_library_mapping_returns_ok_response.yaml b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_library_mapping_returns_ok_response.yaml new file mode 100644 index 0000000000..a9c67744f2 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_validate_an_observability_pipeline_with_ocsf_mapper_library_mapping_returns_ok_response.yaml @@ -0,0 +1,24 @@ +interactions: +- request: + body: '{"data":{"attributes":{"config":{"destinations":[{"id":"datadog-logs-destination","inputs":["my-processor-group"],"type":"datadog_logs"}],"processor_groups":[{"enabled":true,"id":"my-processor-group","include":"service:my-service","inputs":["datadog-agent-source"],"processors":[{"enabled":true,"id":"ocsf-mapper-processor","include":"service:my-service","mappings":[{"include":"source:cloudtrail","mapping":"CloudTrail + Account Change"}],"type":"ocsf_mapper"}]}],"sources":[{"id":"datadog-agent-source","type":"datadog_agent"}]},"name":"OCSF + Mapper Pipeline"},"type":"pipelines"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/obs-pipelines/pipelines/validate + response: + body: + string: '{"errors":[]} + + ' + headers: + content-type: + - application/vnd.api+json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v2/features/observability_pipelines.feature b/tests/v2/features/observability_pipelines.feature index 725b9e425a..b5c6857680 100644 --- a/tests/v2/features/observability_pipelines.feature +++ b/tests/v2/features/observability_pipelines.feature @@ -167,3 +167,26 @@ Feature: Observability Pipelines When the request is sent Then the response status is 200 OK And the response "errors" has length 0 + + @team:DataDog/observability-pipelines + Scenario: Validate an observability pipeline with OCSF mapper custom mapping returns "OK" response + Given new "ValidatePipeline" request + And body with value {"data": {"attributes": {"config": {"destinations": [{"id": "datadog-logs-destination", "inputs": ["my-processor-group"], "type": "datadog_logs"}], "processor_groups": [{"enabled": true, "id": "my-processor-group", "include": "service:my-service", "inputs": ["datadog-agent-source"], "processors": [{"enabled": true, "id": "ocsf-mapper-processor", "include": "service:my-service", "mappings": [{"include": "source:custom", "mapping": {"mapping": [{"default": "", "dest": "time", "source": "timestamp"}, {"default": "", "dest": "severity", "source": "level"}, {"default": "", "dest": "device.type", "lookup": {"table": [{"contains": "Desktop", "value": "desktop"}]}, "source": "host.type"}], "metadata": {"class": "Device Inventory Info", "profiles": ["container"], "version": "1.3.0"}, "version": 1}}], "type": "ocsf_mapper"}]}], "sources": [{"id": "datadog-agent-source", "type": "datadog_agent"}]}, "name": "OCSF Custom Mapper Pipeline"}, "type": "pipelines"}} + When the request is sent + Then the response status is 200 OK + And the response "errors" has length 0 + + @team:DataDog/observability-pipelines + Scenario: Validate an observability pipeline with OCSF mapper invalid custom mapping returns "Bad Request" response + Given new "ValidatePipeline" request + And body with value {"data": {"attributes": {"config": {"destinations": [{"id": "datadog-logs-destination", "inputs": ["my-processor-group"], "type": "datadog_logs"}], "processor_groups": [{"enabled": true, "id": "my-processor-group", "include": "service:my-service", "inputs": ["datadog-agent-source"], "processors": [{"enabled": true, "id": "ocsf-mapper-processor", "include": "service:my-service", "mappings": [{"include": "source:custom", "mapping": {"mapping": [{"dest": "time", "source": "timestamp"}], "metadata": {"class": "Invalid Class", "profiles": ["container"], "version": "1.3.0"}, "version": 0}}], "type": "ocsf_mapper"}]}], "sources": [{"id": "datadog-agent-source", "type": "datadog_agent"}]}, "name": "OCSF Invalid Mapper Pipeline"}, "type": "pipelines"}} + When the request is sent + Then the response status is 400 Bad Request + + @team:DataDog/observability-pipelines + Scenario: Validate an observability pipeline with OCSF mapper library mapping returns "OK" response + Given new "ValidatePipeline" request + And body with value {"data": {"attributes": {"config": {"destinations": [{"id": "datadog-logs-destination", "inputs": ["my-processor-group"], "type": "datadog_logs"}], "processor_groups": [{"enabled": true, "id": "my-processor-group", "include": "service:my-service", "inputs": ["datadog-agent-source"], "processors": [{"enabled": true, "id": "ocsf-mapper-processor", "include": "service:my-service", "type": "ocsf_mapper", "mappings": [{"include": "source:cloudtrail", "mapping": "CloudTrail Account Change"}]}]}], "sources": [{"id": "datadog-agent-source", "type": "datadog_agent"}]}, "name": "OCSF Mapper Pipeline"}, "type": "pipelines"}} + When the request is sent + Then the response status is 200 OK + And the response "errors" has length 0