[RULE: generic_devops_rule] alter get_data = _raw_log ->[0].data{} | alter get_data_IpAddress = get_data -> IpAddress, get_data_ActorCUID = get_data -> ActorCUID, get_data_ProjectId = get_data -> ProjectId | alter IpAddressv4 = if(get_data_IpAddress != null, arrayindex(regextract(get_data_IpAddress, "((?:\d{1,3}\.){3}\d{1,3})"), 0), arrayindex(regextract(IpAddress, "((?:\d{1,3}\.){3}\d{1,3})"), 0)), IpAddressv6 = if(get_data_IpAddress != null, arrayindex(regextract(get_data_IpAddress, "((?:[a-fA-F\d]{0,4}\:){2,7}[a-fA-F\d]{0,4})"), 0), arrayindex(regextract(IpAddress, "((?:[a-fA-F\d]{0,4}\:){2,7}[a-fA-F\d]{0,4})"), 0)), IsUser = if(ActorCUID = "00000000-0000-0000-0000-000000000000" OR get_data_ActorCUID ="00000000-0000-0000-0000-000000000000", to_boolean("False"), to_boolean("True")) | alter xdm.source.user.upn = coalesce(ActorUPN, get_data -> ActorUPN), xdm.source.identity.upn = coalesce(ActorUPN, get_data -> ActorUPN), xdm.source.user.identifier = if(IsUser = False, null, get_data_ActorCUID != null, get_data_ActorCUID, ActorCUID), xdm.source.identity.identifier = if(IsUser = False, null, get_data_ActorCUID != null, get_data_ActorCUID, ActorCUID), xdm.source.user.identity_type = if(IsUser = True, XDM_CONST.IDENTITY_TYPE_USER, XDM_CONST.IDENTITY_TYPE_MACHINE), xdm.source.identity.identity_type = if(IsUser = True, XDM_CONST.IDENTITY_TYPE_USER, XDM_CONST.IDENTITY_TYPE_MACHINE), xdm.auth.auth_method = coalesce(AuthenticationMechanism, get_data -> AuthenticationMechanism), xdm.session_context_id = coalesce(CorrelationId, get_data -> CorrelationId), xdm.event.description = coalesce(Details, get_data -> Details), xdm.source.user.scope = XDM_CONST.SCOPE_TYPE_AZURE, xdm.source.identity.scope = XDM_CONST.SCOPE_TYPE_AZURE, xdm.event.operation_sub_type = coalesce(Category, get_data -> CategoryDisplayName), xdm.source.cloud.project_id = if(ProjectId = "00000000-0000-0000-0000-000000000000" OR get_data_ProjectId = "00000000-0000-0000-0000-000000000000", null, get_data_ProjectId != null, get_data_ProjectId, ProjectId), xdm.source.cloud.project = coalesce(ProjectName, get_data -> ProjectName), xdm.source.user_agent = coalesce(UserAgent, get_data -> UserAgent), xdm.source.ipv4 = IpAddressv4, xdm.source.ipv6 = IpAddressv6, xdm.event.type = coalesce(OperationName, get_data -> OperationName, get_data -> ActionId), xdm.event.id = coalesce(Id, get_data -> Id), xdm.source.cloud.provider = XDM_CONST.CLOUD_PROVIDER_AZURE, xdm.event.original_event_type = coalesce(Type, get_data -> eventType), xdm.event.tags = arraycreate(XDM_CONST.EVENT_TAG_SAAS); [MODEL: dataset = msft_azure_devops_raw] // Licensing events filter Area = "Licensing" OR _raw_log ->[0].data.Area = "Licensing" | call generic_devops_rule | alter get_data_Details = get_data -> Details, get_data_Data = get_data -> Data | alter DetailsUsernameOrGroupName = if(get_data != null, arrayindex(regextract(get_data_Details, "\"(.+)\""),0), arrayindex(regextract(Details,"\"(.+)\""),0)) | alter xdm.target.user.identifier = coalesce(Data -> UserIdentifier, get_data_Data -> UserIdentifier), xdm.target.identity.identifier = coalesce(Data -> UserIdentifier, get_data_Data -> UserIdentifier), xdm.target.user.username = if(Data -> UserIdentifier != null OR get_data_Data -> UserIdentifier != null, DetailsUsernameOrGroupName), xdm.target.identity.username = if(Data -> UserIdentifier != null OR get_data_Data -> UserIdentifier != null, DetailsUsernameOrGroupName), xdm.target.user.groups = if(Data -> GroupIdentifier != null OR get_data_Data -> GroupIdentifier != null, arraycreate(DetailsUsernameOrGroupName)), xdm.target.identity.groups = if(Data -> GroupIdentifier != null OR get_data_Data -> GroupIdentifier != null, arraycreate(DetailsUsernameOrGroupName)), xdm.event.outcome_reason = coalesce(Data -> Reason, get_data_Data -> Reason), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Extension events filter Area = "Extension" OR _raw_log ->[0].data.Area = "Extension" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter xdm.target.application.publisher = coalesce(Data -> PublisherName, get_data_Data -> PublisherName), xdm.target.application.name = coalesce(Data -> ExtensionName, get_data_Data -> ExtensionName), xdm.target.application.version = coalesce(Data -> Version, get_data_Data -> Version), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Git events filter Area = "Git" OR _raw_log ->[0].data.Area = "Git" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter //xdm mapping xdm.target.resource.type = "Git Repository", xdm.target.resource.id = coalesce(Data -> RepoId, get_data_Data -> RepoId), xdm.target.resource.name = coalesce(Data -> RepoName, get_data_Data -> RepoName), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Group events filter Area = "Group" OR _raw_log ->[0].data.Area = "Group" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter xdm.source.process.name = coalesce(Data -> CallerProcedure, get_data_Data -> CallerProcedure), xdm.target.user.groups = if(get_data != null, arraycreate(concat("Id: ", get_data_Data -> GroupId), concat("Name: ", get_data_Data -> GroupName)), arraycreate(concat("Id: ",Data -> GroupId), concat("Name: ", Data -> GroupName))), xdm.target.identity.groups = if(get_data != null, arraycreate(concat("Id: ", get_data_Data -> GroupId), concat("Name: ", get_data_Data -> GroupName)), arraycreate(concat("Id: ",Data -> GroupId), concat("Name: ", Data -> GroupName))), xdm.target.user.identifier = coalesce(Data -> MemberId, get_data_Data -> MemberId), xdm.target.identity.identifier = coalesce(Data -> MemberId, get_data_Data -> MemberId), xdm.target.user.username = coalesce(Data -> MemberDisplayName, get_data_Data -> MemberDisplayName), xdm.target.identity.username = coalesce(Data -> MemberDisplayName, get_data_Data -> MemberDisplayName), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Library events filter Area = "Library" OR _raw_log ->[0].data.Area = "Library" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter AgentPoolId = coalesce(Data -> AgentPoolId, get_data_Data -> AgentPoolId), AgentPoolName = coalesce(Data -> AgentPoolName, get_data_Data -> AgentPoolName), ConnectionId = coalesce(Data -> ConnectionId, get_data_Data -> ConnectionId), ConnectionName = coalesce(Data -> ConnectionName, get_data_Data -> ConnectionName), VariableGroupId = coalesce(Data -> VariableGroupId, get_data_Data -> VariableGroupId), VariableGroupName = coalesce(Data -> VariableGroupName, get_data_Data -> VariableGroupName) | alter ResourceType = if(AgentPoolId != null, to_string("Agent Pool"), ConnectionId != null, to_string("Service Connection"), VariableGroupId != null, to_string("Variable Group")) | alter xdm.target.agent.identifier = coalesce(Data -> AgentName, get_data_Data -> AgentName), xdm.network.session_id = ConnectionId, xdm.target.resource.id = coalesce(AgentPoolId, ConnectionId, VariableGroupId), xdm.target.resource.name = coalesce(AgentPoolName, ConnectionName, VariableGroupName), xdm.target.resource.type = ResourceType, xdm.target.resource.sub_type = coalesce(Data -> ConnectionType, get_data_Data -> ConnectionType, Data -> VariableGroupType, get_data_Data -> VariableGroupType, Data -> Type, get_data_Data -> Type), xdm.source.process.name = coalesce(Data -> CallerProcedure, get_data_Data -> CallerProcedure), xdm.target.agent.type = if(Data -> AgentId != null OR get_data_Data -> AgentId != null, XDM_CONST.AGENT_TYPE_CLOUD), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Token events filter Area = "Token" OR _raw_log ->[0].data.Area = "Token" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter OwnerName = if(get_data_Data -> OwnerName != null, arrayindex(regextract(get_data_Data -> OwnerName, "user\s\"(.+)\""),0), Data -> OwnerName != null ,arrayindex(regextract(Data -> OwnerName, "user\s\"(.+)\""),0)), TokenType = if(OperationName CONTAINS "Ssh", "SSH Key", get_data -> OperationName CONTAINS "Ssh", "SSH Key", "Personal Access Token") | alter //xdm mapping xdm.target.resource.type = TokenType, xdm.target.resource.sub_type = coalesce(Data -> TokenType, get_data_Data -> TokenType), xdm.target.resource.name = coalesce(Data -> DisplayName, get_data_Data -> DisplayName), xdm.target.user.identifier = coalesce(Data -> TargetUser, get_data_Data -> TargetUser), xdm.target.identity.identifier = coalesce(Data -> TargetUser, get_data_Data -> TargetUser), xdm.target.user.username = OwnerName, xdm.target.identity.username = OwnerName, xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Policy events filter Area = "Policy" OR _raw_log ->[0].data.Area = "Policy" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter //xdm mapping xdm.target.resource.id = coalesce(Data -> PolicyTypeId, get_data_Data -> PolicyTypeId), xdm.target.resource.name = coalesce(Data -> PolicyTypeDisplayName, get_data_Data -> PolicyTypeDisplayName), xdm.target.resource.type = to_string("Policy"), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Project events filter Area = "Project" OR _raw_log ->[0].data.Area = "Project" | call generic_devops_rule | alter get_data_Data = get_data -> Data, ResourceType = if(OperationName IN ("*Area*"), to_string("Area Path"), get_data -> OperationName IN ("*Area*"), to_string("Area Path"), OperationName IN ("*IterationPath*"), to_string("Iteration Path"), get_data -> OperationName IN ("*IterationPath*"), to_string("Iteration Path")) | alter //xdm mapping xdm.target.process.name = coalesce(Data -> ProcessName, get_data_Data -> processName), xdm.target.resource.name = coalesce(Data -> Path, get_data_Data -> Path), xdm.target.resource.type = ResourceType, xdm.event.outcome = if(OperationName IN ("*Failed"),XDM_CONST.OUTCOME_FAILED, get_data -> OperationName IN ("*Failed"), XDM_CONST.OUTCOME_FAILED, OperationName IN("*Queued"), XDM_CONST.OUTCOME_PARTIAL, get_data -> OperationName IN("*Queued"), XDM_CONST.OUTCOME_PARTIAL, OperationName IN ("*Completed","Project.AreaPath.Create", "Project.AreaPath.Delete", "Project.AreaPath.Update", "Project.IterationPath.Create", "Project.IterationPath.Update", "Project.IterationPath.Delete", "Project.Process.Modify", "Project.Process.ModifyWithoutOldProcess") ,XDM_CONST.OUTCOME_SUCCESS, get_data -> OperationName IN ("*Completed","Project.AreaPath.Create", "Project.AreaPath.Delete", "Project.AreaPath.Update", "Project.IterationPath.Create", "Project.IterationPath.Update", "Project.IterationPath.Delete", "Project.Process.Modify", "Project.Process.ModifyWithoutOldProcess") ,XDM_CONST.OUTCOME_SUCCESS, XDM_CONST.OUTCOME_UNKNOWN); //Release events filter Area = "Release" OR _raw_log ->[0].data.Area = "Release" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter ResourceType = if(OperationName IN ("*Pipeline*"), to_string("Release Pipeline"), get_data -> OperationName IN ("*Pipeline*"), to_string("Release Pipeline"), to_string("Release")), ReleaseId = coalesce(Data -> ReleaseId, get_data_Data -> ReleaseId) | alter //xdm mapping xdm.source.process.name = coalesce(Data -> CallerProcedure, get_data_Data -> CallerProcedure), xdm.target.resource.id = if(ResourceType = "Release Pipeline" AND get_data = null, Data -> PipelineId, ResourceType = "Release Pipeline", get_data_Data -> PipeLineId, ReleaseId != null, ReleaseId, get_data_Data = null, Data -> ReleaseEnvironmentSteps[0].ReleaseId, get_data_Data -> ReleaseEnvironmentSteps[0].ReleaseId), xdm.target.resource.name = if(ResourceType = "Release Pipeline" AND get_data = null, Data -> PipeLineName, ResourceType = "Release Pipeline", get_data_Data -> PipeLineName, get_data_Data = null, Data -> ReleaseName, get_data_Data -> ReleaseName), xdm.target.resource.type = ResourceType, xdm.event.outcome_reason = coalesce(Data -> ApprovalType, get_data_Data -> ApprovalType, Data -> Reason, get_data_Data -> Reason), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Security events filter Area = "Permissions" OR _raw_log ->[0].data.Area = "Permissions" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter SubjectDisplayName = coalesce(Data -> SubjectDisplayName, get_data_Data -> SubjectDisplayName), SubjectDescriptor = coalesce(Data -> SubjectDescriptor, get_data_Data -> SubjectDescriptor), ChangedPermission = coalesce(Data -> ChangedPermission, get_data_Data -> ChangedPermission) | alter //xdm mapping xdm.target.zone = coalesce(Data -> NamespaceName, get_data_Data -> NamespaceName), xdm.target.agent.identifier = coalesce(Data -> Token, get_data_Data -> Token), xdm.target.resource.type = if(Data -> SubjectDisplayName != null OR get_data_Data -> SubjectDisplayName != null, "Permission"), xdm.target.resource.value = coalesce(Data -> PermissionModifiedTo, get_data_Data -> PermissionModifiedTo), xdm.target.resource.name = if(ChangedPermission != null, ChangedPermission, get_data_Data = null, to_string(arraymap(Data -> EventSummary[], "@element" -> PermissionNames)), to_string(arraymap(get_data_Data -> eventSummary[], "@element" -> permissionNames))), xdm.target.user.groups = if(SubjectDescriptor = null, arraycreate(SubjectDisplayName)), xdm.target.identity.groups = if(SubjectDescriptor = null, arraycreate(SubjectDisplayName)), xdm.target.user.upn = if(SubjectDescriptor != null, arrayindex(regextract(SubjectDescriptor, ".+\\+(.+)"),0)), xdm.target.identity.upn = if(SubjectDescriptor != null, arrayindex(regextract(SubjectDescriptor, ".+\\+(.+)"),0)), xdm.target.user.username = if(SubjectDescriptor != null, SubjectDisplayName), xdm.target.identity.username = if(SubjectDescriptor != null, SubjectDisplayName), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Pipelines events filter Area = "Pipelines" OR _raw_log ->[0].data.Area = "Pipelines" | call generic_devops_rule | alter get_data_Data = get_data -> Data | alter isResource = if(Data -> ResourceId != null OR get_data_Data -> ResourceId != null, to_boolean("True"), to_boolean("False")) | alter //xdm mapping xdm.target.zone = coalesce(Data -> EnvironmentName, get_data_Data -> EnvironmentName), xdm.target.resource.type = if(isResource = True AND get_data_Data = null, Data -> ResourceType, isResource = True, get_data_Data -> ResourceType, to_string("Pipeline")), xdm.target.resource.id = if(isResource = True AND get_data_Data = null, Data -> ResourceId, isResource = True, get_data_Data -> ResourceId, get_data_Data = null, Data -> PipelineId, get_data_Data -> PipelineId), xdm.source.process.name = coalesce(Data -> CallerProcedure, get_data_Data -> callerProcedure), xdm.event.outcome = XDM_CONST.OUTCOME_SUCCESS; //Fallback to whats not in the event types we are mapping filter Area NOT IN ("Licensing", "Extension", "Git", "Group", "Library", "Token", "Policy", "Project", "Release", "Permissions", "Pipelines") AND _raw_log ->[0].data.Area NOT IN ("Licensing", "Extension", "Git", "Group", "Library", "Token", "Policy", "Project", "Release", "Permissions", "Pipelines") | call generic_devops_rule;