Azure DevOps Modeling Rule

Modeling Rule

AzureDevOps

Details

IDAzure_DevOps_ModelingRule
From Version8.5.0

Rules (XIF)

[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.user.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.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.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.user.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.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.user.identifier = coalesce(Data -> MemberId, get_data_Data -> MemberId),
    xdm.target.user.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.user.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.user.upn = if(SubjectDescriptor != null, arrayindex(regextract(SubjectDescriptor, ".+\\+(.+)"),0)),
    xdm.target.user.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;

Schema

msft_azure_devops_raw

Field Type Array?
ActorCUID string
ActorUPN string
Area string
AuthenticationMechanism string
Category string
CorrelationId string
Data string
Details string
Id string
IpAddress string
OperationName string
ProjectId string
ProjectName string
TimeGenerated datetime
Type string
UserAgent string
_raw_log string
Raw JSON
{
    "msft_azure_devops_raw": {
        "ActorCUID": {
            "type": "string",
            "is_array": false
        },
        "ActorUPN": {
            "type": "string",
            "is_array": false
        },
        "Area": {
            "type": "string",
            "is_array": false
        },
        "AuthenticationMechanism": {
            "type": "string",
            "is_array": false
        },
        "Category": {
            "type": "string",
            "is_array": false
        },
        "CorrelationId": {
            "type": "string",
            "is_array": false
        },
        "Data": {
            "type": "string",
            "is_array": false
        },
        "Details": {
            "type": "string",
            "is_array": false
        },
        "IpAddress": {
            "type": "string",
            "is_array": false
        },
        "OperationName": {
            "type": "string",
            "is_array": false
        },
        "ProjectId": {
            "type": "string",
            "is_array": false
        },
        "ProjectName": {
            "type": "string",
            "is_array": false
        },
        "Type": {
            "type": "string",
            "is_array": false
        },
        "UserAgent": {
            "type": "string",
            "is_array": false
        },
        "_raw_log": {
            "type": "string",
            "is_array": false
        },
        "Id": {
            "type": "string",
            "is_array": false
        },
        "TimeGenerated": {
            "type": "datetime",
            "is_array": false
        }
    }
}