Closed andrewkroh closed 5 months ago
Pinging @elastic/security-external-integrations (Team:Security-External Integrations)
I have made some corrections and additions to the ingest pipeline that @andrewkroh has put here Netscaler Pipeline Gist
This I have working in production at the moment.
PUT _ingest/pipeline/citrix_netscaler
{
"processors": [
{
"script": {
"description": "set event.original",
"lang": "painless",
"source": "def event = ctx.event;\nif (event == null) {\n event = [:];\n ctx['event'] = event;\n}\nevent['original'] = ctx.message;\n"
}
},
{
"set": {
"field": "event.ingested",
"value": "{{_ingest.timestamp}}"
}
},
{
"set": {
"field": "observer.vendor",
"value": "Citrix"
}
},
{
"set": {
"field": "observer.product",
"value": "Netscaler"
}
},
{
"set": {
"field": "observer.type",
"value": "firewall"
}
},
{
"set": {
"field": "event.module",
"value": "citrix"
}
},
{
"set": {
"field": "event.dataset",
"value": "citrix.netscaler"
}
},
{
"grok": {
"description": "grok syslog header",
"field": "message",
"patterns": [
"<%{NONNEGINT:log.syslog.facility.code:long}> %{NOTSPACE:timestamp} ?%{WORD:event.timezone}? %{HOSTNAME:host.name} %{HOSTNAME} : %{GREEDYDATA:message}"
]
}
},
{
"grok": {
"description": "grok citrix header",
"field": "message",
"patterns": [
"%{WORD} %{WORD:citrix.netscaler.feature} %{WORD:citrix.netscaler.message_type} %{NUMBER} %{NUMBER} :%{SPACE}+%{GREEDYDATA:message}"
]
}
},
{
"lowercase": {
"field": "citrix.netscaler.feature"
}
},
{
"lowercase": {
"field": "citrix.netscaler.message_type"
}
},
{
"date": {
"field": "timestamp",
"target_field": "@timestamp",
"formats": [
"MM/dd/yyyy:HH:mm:ss"
],
"timezone": "{{event.timezone}}",
"if": "ctx?.event?.timezone != null"
}
},
{
"date": {
"field": "timestamp",
"target_field": "@timestamp",
"formats": [
"MM/dd/yyyy:HH:mm:ss"
],
"if": "ctx?.event?.timezone == null"
}
},
{
"remove": {
"field": [
"timestamp"
]
}
},
{
"set": {
"description": "set event.code",
"field": "event.code",
"value": "{{citrix.netscaler.feature}}-{{citrix.netscaler.message_type}}"
}
},
{
"set": {
"description": "set generic event.action",
"field": "event.action",
"value": "{{citrix.netscaler.feature}} {{citrix.netscaler.message_type}}"
}
},
{
"script": {
"lang": "painless",
"source": "ctx.event.kind = 'event';\nctx.event.type = ['info'];\nctx.event.outcome = 'success';\n\ndef metadata = params.get(ctx.event.code);\nif (metadata == null) {\n return;\n}\nmetadata.forEach((k, v) -> ctx.event[k] = v);\n",
"params": {
"api-cmd_executed": {
"category": [
"process"
],
"type": [
"start"
],
"action": "command executed"
},
"cli-cmd_executed": {
"category": [
"process"
],
"type": [
"start"
],
"action": "command executed"
},
"gui-cmd_executed": {
"category": [
"process"
],
"type": [
"start"
],
"action": "command executed"
},
"ui-cmd_executed": {
"category": [
"process"
],
"type": [
"start"
],
"action": "command executed"
},
"aaa-login_failed": {
"category": [
"authentication"
],
"type": [
"denied"
],
"outcome": "failure",
"action": "login failed"
},
"sslvpn-icastart": {
"category": [
"process",
"network"
],
"type": [
"start"
],
"action": "ICA application started"
},
"sslvpn-icaend_connstat": {
"category": [
"process",
"network"
],
"type": [
"end",
"connection"
],
"action": "ICA application ended"
},
"sslvpn-tcpconnstat": {
"category": [
"network"
],
"type": [
"end",
"connection"
],
"action": "tcp connection ended"
},
"tcp-conn_terminate": {
"category": [
"network"
],
"type": [
"end",
"connection"
],
"action": "tcp connection terminated"
},
"tcp-conn_delink": {
"category": [
"network"
],
"type": [
"end",
"connection"
],
"action": "tcp connection delinked"
},
"tcp-otherconn_delink": {
"category": [
"network"
],
"type": [
"end"
],
"action": "connection delinked"
},
"aaatm-httprequest": {
"category": [
"network",
"web"
],
"type": [
"protocol",
"start",
"info"
],
"action": "http request"
},
"sslvpn-httprequest": {
"category": [
"network",
"web"
],
"type": [
"protocol",
"start",
"info"
],
"action": "http request"
},
"ssllog-ssl_handshake_success": {
"category": [
"session"
],
"type": [
"start",
"info"
],
"action": "handshake success"
},
"ssllog-ssl_handshake_issuername": {
"category": [
"session"
],
"type": [
"info"
],
"action": "handshake issuer"
},
"ssllog-ssl_handshake_subjectname": {
"category": [
"session"
],
"type": [
"info"
],
"action": "handshake subject"
},
"ssllog-ssl_handshake_failure": {
"category": [
"session"
],
"type": [
"error"
],
"outcome": "failure",
"action": "handshake failed"
},
"rewrite-message": {
"category": [
"web"
],
"type": [
"info"
],
"action": "rewrite message"
},
"aaatm-login": {
"category": [
"authentication"
],
"type": [
"start"
]
},
"sslvpn-login": {
"category": [
"authentication"
],
"type": [
"start"
]
},
"aaatm-logout": {
"category": [
"authentication"
],
"type": [
"end"
]
},
"sslvpn-logout": {
"category": [
"authentication"
],
"type": [
"end"
]
}
},
"tag": "ecs_categorize",
"description": "add event category and type"
}
},
{
"dissect": {
"field": "message",
"pattern": "\"%{event.reason}: Client_IP: %{source.ip} - Request URL:%{url.original} - LB_vServer: %{observer.name}\"",
"if": "ctx?.event?.code == \"rewrite-message\"",
"description": "rewrite-message",
"on_failure": [
{
"gsub": {
"field": "message",
"pattern": "\"$",
"replacement": "",
"ignore_missing": true,
"description": "Remove trailing quotes"
}
},
{
"dissect": {
"field": "message",
"pattern": "\"%{event.reason}: Client_IP: %{source.ip} - Request URL:%{url.original}",
"description": "rewrite-message short"
}
}
]
}
},
{
"dissect": {
"field": "message",
"pattern": "User %{user.name} - Remote_ip %{source.ip} - Command \"%{CommandLine}\" - Status \"%{citrix.netscaler.status}\"",
"if": "ctx?.event?.code == \"api-cmd_executed\"",
"description": "api-cmd_executed"
}
},
{
"dissect": {
"field": "message",
"pattern": "User %{user.name} - Remote_ip %{source.ip} - Command \"%{CommandLine}\" - Status \"%{citrix.netscaler.status}\"",
"if": "ctx?.event?.code == \"cli-cmd_executed\"",
"description": "cli-cmd_executed"
}
},
{
"dissect": {
"field": "message",
"pattern": "User %{user.name} - Remote_ip %{source.ip} - Command \"%{CommandLine}\" - Status \"%{citrix.netscaler.status}\"",
"if": "ctx?.event?.code == \"gui-cmd_executed\"",
"description": "gui-cmd_executed"
}
},
{
"dissect": {
"field": "message",
"pattern": "User %{user.name} - Remote_ip %{source.ip} - Command \"%{CommandLine}\" - Status \"%{citrix.netscaler.status}\"",
"if": "ctx?.event?.code == \"ui-cmd_executed\"",
"description": "ui-cmd_executed"
}
},
{
"dissect": {
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id}- %{destination.domain} User %{} : Group(s) %{citrix.netscaler.group} : Vserver %{destination.ip}:%{destination.port} - %{} : SSO is %{} : %{http.request.method} %{url.original} - -",
"if": "ctx?.event?.code == \"sslvpn-httprequest\"",
"description": "sslvpn-httprequest"
}
},
{
"dissect": {
"field": "message",
"pattern": "Context %{user.name}@%{user.domain}@%{source.ip} - SessionId: %{citrix.netscaler.session_id} - %{destination.domain} User %{user.name} : Group(s) %{citrix.netscaler.group} : Vserver %{destination.ip}:%{destination.port} - %{} : SSO is %{} : %{http.request.method} %{url.original} - -",
"if": "ctx?.event?.code == \"aaatm-httprequest\"",
"description": "aaatm-httprequest",
"on_failure": [
{
"dissect": {
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id} - %{destination.domain} User %{user.name} : Group(s) %{citrix.netscaler.group} : Vserver %{destination.ip}:%{destination.port} - %{} : SSO is %{} : %{http.request.method} %{url.original} - -"
}
}
]
}
},
{
"dissect": {
"field": "message",
"pattern": "Command \"%{process.command_line}\" %{}",
"if": "ctx?.event?.code == \"routing-zebos_cmd_executed\"",
"description": "routing-zebos_cmd_executed"
}
},
{
"dissect": {
"field": "message",
"pattern": "Source %{source.ip}:%{source.port} - Destination %{destination.ip}:%{destination.port} - Start Time %{event.start} %{event.timezone} - End Time %{event.end} %{event.timezone} - Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes} ",
"if": "ctx?.event?.code == \"tcp-conn_terminate\"",
"description": "tcp-conn_terminate"
}
},
{
"dissect": {
"field": "message",
"pattern": "Source %{source.ip}:%{source.port} - Vserver %{destination.ip}:%{destination.port} - NatIP %{source.nat.ip}:%{source.nat.port} - Destination %{destination.nat.ip}:%{destination.nat.port} - Delink Time %{event.end} %{event.timezone} - Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes}",
"if": "ctx?.event?.code == \"tcp-conn_delink\"",
"description": "tcp-conn_delink"
}
},
{
"dissect": {
"field": "message",
"pattern": "Source %{source.ip}:%{source.port} - Vserver %{destination.ip}:%{destination.port} - NatIP %{source.nat.ip}:%{source.nat.port} - Destination %{destination.nat.ip}:%{destination.nat.port} - Delink Time %{event.end} %{event.timezone} Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes}",
"if": "ctx?.event?.code == \"tcp-otherconn_delink\"",
"description": "tcp-otherconn_delink"
}
},
{
"grok": {
"field": "message",
"patterns": [
"^\"SSO ns_sslvpn_process_sso_conn: user %{DATA:user.name} clientip %{IP:source.ip} request: %{URIPATHPARAM:url.original} %{GREEDYDATA:message}\"$",
"^\"SSO nssso_res_hdr_handler-forward_2_client : user %{DATA:user.name} clientip %{IP:source.ip} %{DATA} response-%{INT:http.response.status_code} session-id-%{INT:citrix.netscaler.session_id} %{GREEDYDATA:message}\"$",
"^\"SSO nssso_res_hdr_handler : user %{DATA:user.name} clientip %{IP:source.ip} %{DATA} response-%{INT:http.response.status_code} session-id-%{INT:citrix.netscaler.session_id} %{GREEDYDATA:message}\"$",
"^\"SSO sso_clt_output_handler : user %{DATA:user.name} clientip %{IP:source.ip} %{DATA} response-%{INT:http.response.status_code} session-id-%{INT:citrix.netscaler.session_id} %{GREEDYDATA:message}\"$",
"^\"SSO sso_svr_output_handler-after : user %{DATA:user.name} clientip %{IP:source.ip} %{DATA} response-%{INT:http.response.status_code} session-id-%{INT:citrix.netscaler.session_id} %{GREEDYDATA:message}\"$",
"^\"SSO sso_svr_output_handler : user %{DATA:user.name} clientip %{IP:source.ip} %{DATA} response-%{INT:http.response.status_code} session-id-%{INT:citrix.netscaler.session_id} %{GREEDYDATA:message}\"$",
"^\"SSO ns_sslvpn_process_sso_conn: After Initialization user %{DATA:user.name} clientip %{IP:source.ip} %{GREEDYDATA:message}\"$"
],
"if": "ctx?.event?.code == \"sslvpn-message\"",
"ignore_failure": true,
"description": "sslvpn-message"
}
},
{
"grok": {
"field": "message",
"patterns": [
"^\"CGI/TM: Computed url with csrf is %{URI:url.original}$",
"^\"prepare cgi/tm: data being stored is: %{INT} %{DATA:url.original}\"$",
"^\"restarting force timer for <%{DATA:user.name}> for %{INT} min\"$"
],
"if": "ctx?.event?.code == \"aaatm-message\"",
"ignore_failure": true,
"description": "aaatm-message"
}
},
{
"grok": {
"field": "message",
"patterns": [
"^\"In update_aaa_cntr: Succeeded policy for user %{DATA:user.name} = %{DATA:observer.name}\"$",
"^\"rba_server_handler Authentication complete for user %{DATA:user.name}\"$",
"^\"AAAD RESP: received resp,user: <%{DATA:user.name}>, factor: <%{DATA:observer.name}>, %{GREEDYDATA}$",
"^\"Allowing CitrixAGBasicSSO for %{DATA} request {user=%{DATA:user.name}}\"$"
],
"if": "ctx?.event?.code == \"aaa-message\"",
"ignore_failure": true,
"description": "aaa-message"
}
},
{
"grok": {
"field": "message",
"patterns": [
"^netScaler%{DATA:process.name} (nsUserName = \"%{DATA:user.name}\", configurationCmd = \"%{DATA:process.command_line}\", authorizationStatus = %{DATA}, commandExecutionStatus = %{DATA}, nsClientIPAddr = %{DATA:client.ip}, nsPartitionName = %{DATA})$",
"^netScaler%{DATA:process.name} (nsUserName = \"%{DATA:user.name}\", commandExecutionStatus = %{DATA}, nsPartitionName = %{DATA})$"
],
"if": "ctx?.event?.code == \"snmp-trap_sent\"",
"ignore_failure": true,
"description": "snmp-trap_sent"
}
},
{
"set": {
"description": "sslvpn-httprequest network.protocol http",
"if": "ctx?.event?.code == \"sslvpn-httprequest\"",
"field": "network.protocol",
"value": "http"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"sslvpn-httprequest\"",
"description": "sslvpn-httprequest network.transport tcp"
}
},
{
"set": {
"field": "network.protocol",
"value": "http",
"if": "ctx?.event?.code == \"aaatm-httprequest\"",
"description": "aaatm-httprequest network.protocol http"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"aaatm-httprequest\"",
"description": "aaatm-httprequest network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"tcp-conn_terminate\"",
"description": "tcp-conn_terminate network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"tcp-conn_delink\"",
"description": "tcp-conn_delink network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"tcp-otherconn_delink\"",
"description": "tcp-otherconn_delink network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_success\"",
"description": "ssllog-ssl_handshake_success network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_failure\"",
"description": "ssllog-ssl_handshake_success network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"sslvpn-icaend_connstat\"",
"description": "sslvpn-icaend_connstat network.transport tcp"
}
},
{
"set": {
"field": "network.transport",
"value": "tcp",
"if": "ctx?.event?.code == \"sslvpn-tcpconnstat\"",
"description": "sslvpn-tcpconnstat network.transport tcp"
}
},
{
"set": {
"field": "network.iana_number",
"value": "6",
"if": "ctx?.network?.transport == \"tcp\"",
"description": "if network.transport tcp set iana"
}
},
{
"grok": {
"field": "url.original",
"ignore_failure": true,
"patterns": [
"%{URIPATH:url.path}(?:%{URIPARAM:url.query})?"
]
}
},
{
"dissect": {
"field": "message",
"pattern": "User %{user.name} - Client_ip %{source.ip} - Failure_reason \"%{event.reason}\" - Browser %{user_agent.original}",
"if": "ctx?.event?.code == \"aaa-login_failed\"",
"description": "aaa-login_failed"
}
},
{
"dissect": {
"field": "message",
"pattern": "Extracted_groups \"%{citrix.netscaler.group}\"",
"if": "ctx?.event?.code == \"aaa-extracted_groups\"",
"description": "aaa-extracted_groups"
}
},
{
"dissect": {
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id} - User %{user.name} - Client_ip %{source.ip} - Nat_ip \"%{}\" - Vserver %{destination.ip}:%{destination.port} - Browser_type \"%{user_agent.original}\" - Group(s) \"%{citrix.netscaler.group}\"",
"if": "ctx?.event?.code == \"aaatm-login\"",
"description": "aaatm-login"
}
},
{
"dissect": {
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id} - User %{user.name} - Client_ip %{source.ip} - Nat_ip \"%{}\" - Vserver %{destination.ip}:%{destination.port} - Start_time \"%{event.start} %{event.timezone}\" - End_time \"%{event.end} %{event.timezone}\" - Duration %{} - Http_resources_accessed %{} - Total_TCP_connections %{} - Total_policies_allowed %{} - Total_policies_denied %{} - Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes} - Total_compressedbytes_send %{} - Total_compressedbytes_recv %{} - Compression_ratio_send %{} - Compression_ratio_recv %{} - LogoutMethod %{} - Group(s) \"%{citrix.netscaler.group}\"",
"if": "ctx?.event?.code == \"aaatm-logout\"",
"description": "aaatm-logout"
}
},
{
"dissect": {
"field": "message",
"pattern": "SPCBId %{event.id} - ClientIP %{source.ip} - ClientPort %{source.port} - VserverServiceIP %{destination.ip} - VserverServicePort %{destination.port} - ClientVersion %{tls.version_protocol}v%{tls.version} - CipherSuite \"%{tls.cipher}\" - Session %{} - %{} -SerialNumber \"%{x509.serial_number}\" - SignatureAlgorithm \"%{x509.signature_algorithm}\" - ValidFrom \"%{x509.not_before}\" - ValidTo \"%{x509.not_after}\" - HandshakeTime %{}",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_success\" && ctx?.message.startsWith(\"SPCBId\")",
"description": "ssllog-ssl_handshake_success - client",
"on_failure": [
{
"dissect": {
"field": "message",
"pattern": "SPCBId %{event.id} - ClientIP %{source.ip} - ClientPort %{source.port} - VserverServiceIP %{destination.ip} - VserverServicePort %{destination.port} - ClientVersion %{tls.version_protocol}v%{tls.version} - CipherSuite \"%{tls.cipher}\" - Session %{} - HandshakeTime %{}",
"description": "ssllog-ssl_handshake_success - client short"
}
}
]
}
},
{
"dissect": {
"field": "message",
"pattern": "Backend SPCBId %{event.id} - ServerIP %{source.ip} - ServerPort %{source.port} - ProtocolVersion %{tls.version_protocol}v%{tls.version} - CipherSuite \"%{tls.cipher}\" - Session %{} - %{} -SerialNumber \"%{x509.serial_number}\" - SignatureAlgorithm \"%{x509.signature_algorithm}\" - ValidFrom \"%{x509.not_before}\" - ValidTo \"%{x509.not_after}\" - HandshakeTime %{}",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_success\" && ctx?.message.startsWith(\"Backend\")",
"description": "ssllog-ssl_handshake_success - backend"
}
},
{
"dissect": {
"field": "message",
"pattern": "SPCBId %{event.id} - IssuerName \"%{tls.server.issuer}\"",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_issuername\"",
"description": "ssllog-ssl_handshake_issuername"
}
},
{
"dissect": {
"field": "message",
"pattern": "SPCBId %{event.id} - SubjectName \"%{tls.server.subject}\"",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_subjectname\"",
"description": "ssllog-ssl_handshake_subjectname"
}
},
{
"dissect": {
"field": "message",
"pattern": "SPCBId %{event.id} - ClientIP %{source.ip} - ClientPort %{source.port} - VserverServiceIP %{destination.ip} - VserverServicePort %{destination.port} - ClientVersion %{tls.version_protocol}v%{tls.version} - CipherSuite \"%{tls.cipher}\" - Reason \"%{error.message}\"",
"if": "ctx?.event?.code == \"ssllog-ssl_handshake_failure\"",
"description": "ssllog-ssllog-ssl_handshake_failure"
}
},
{
"dissect": {
"field": "message",
"pattern": "crl_name %{} - server_port %{destination.port} - method %{} - crl_url \"%{url.original}\"",
"if": "ctx?.event?.code == \"ssllog-ssl_crl_update_success\"",
"description": "ssllog-ssl_crl_update_success"
}
},
{
"dissect": {
"field": "message",
"pattern": "crl_name %{} - server_port %{destination.port} - method %{} - crl_url \"%{url.original}\" - Reason \"%{event.reason}\"",
"if": "ctx?.event?.code == \"ssllog-ssl_crl_update_failure\"",
"description": "ssllog-ssl_crl_update_failure"
}
},
{
"dissect": {
"field": "message",
"pattern": "Source %{source.ip}:%{source.port} - Destination %{destination.ip}:%{destination.port} - username:domainname %{user.name}:%{user.domain} - applicationName %{observer.name} - startTime \"%{event.start} %{event.timezone}\" - connectionId %{citrix.netscaler.connection_id}",
"if": "ctx?.event?.code == \"sslvpn-icastart\"",
"description": "sslvpn-icastart"
}
},
{
"dissect": {
"field": "message",
"pattern": "Source %{source.ip}:%{source.port} - Destination %{destination.ip}:%{destination.port} - %{} - username:domainname %{user.name}:%{user.domain} - startTime \"%{event.start} %{event.timezone}\" - endTime \"%{event.end} %{event.timezone}\" - Duration %{} - Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes} - Total_compressedbytes_send %{citrix.netscaler.total_compressed_bytes_send} - Total_compressedbytes_recv %{citrix.netscaler.total_compressed_bytes_recv} - Compression_ratio_send %{} - Compression_ratio_recv %{} - connectionId %{citrix.netscaler.connection_id} - Total_bytes_wire_send %{} - Total_bytes_wire_recv %{}",
"if": "ctx?.event?.code == \"sslvpn-icaend_connstat\"",
"description": "sslvpn-icaend_connstat"
}
},
{
"dissect": {
"description": "sslvpn-login",
"if": "ctx?.event?.code == \"sslvpn-login\"",
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id}- User %{} - Client_ip %{} - Nat_ip \"%{}\" - Vserver %{citrix.netscaler.vserver}:%{destination.port} - Browser_type \"%{user_agent.original}\" - SSLVPN_client_type %{citrix.netscaler.vpn_client_type} - Group(s) \"%{citrix.netscaler.group}\""
}
},
{
"dissect": {
"field": "message",
"pattern": "SessionId %{citrix.netscaler.session_id} - User %{user.name} - Client_ip %{source.ip} - Nat_ip \"%{}\" - Vserver_ip %{destination.ip} - Errmsg \"%{error.message}\"",
"if": "ctx?.event?.code == \"sslvpn-remove_session_debug\"",
"description": "sslvpn-remove_session_debug"
}
},
{
"dissect": {
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id} - User %{user.name} - Client_ip %{source.ip} - Nat_ip %{source.nat.ip} - Vserver %{destination.ip}:%{destination.port} - Source %{source.ip}:%{source.port} - Destination %{destination.ip}:%{destination.port} - Start_time \"%{event.start} %{event.timezone}\" - End_time \"%{event.end} %{event.timezone}\" - Duration %{} - Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes} - Total_compressedbytes_send %{citrix.netscaler.total_compressed_bytes_send} - Total_compressedbytes_recv %{citrix.netscaler.total_compressed_bytes_recv} - Compression_ratio_send %{} - Compression_ratio_recv %{} - Access %{event.reason} - Group(s) \"%{citrix.netscaler.group}\"",
"if": "ctx?.event?.code == \"sslvpn-tcpconnstat\"",
"description": "sslvpn-tcpconnstat"
}
},
{
"dissect": {
"description": "sslvpn-logout-with-context-header",
"if": "ctx?.event?.code == \"sslvpn-logout\" && ctx?.message.startsWith(\"Context\")",
"field": "message",
"pattern": "Context %{user.name}@%{source.ip} - SessionId: %{citrix.netscaler.session_id}- User %{} - %{}"
}
},
{
"grok": {
"description": "sslvpn-logout-without-context-header",
"if": "ctx?.event?.code == \"sslvpn-logout\" && !ctx?.message.startsWith(\"Context\")",
"field": "message",
"patterns": [
"User %{NOTSPACE:user.name}?%{SPACE}?- "
]
}
},
{
"dissect": {
"field": "message",
"pattern": "%{} - Client_ip %{source.ip} - Nat_ip \"%{}\" - Vserver %{destination.ip}:%{destination.port} - Start_time \"%{event.start} %{event.timezone}\" - End_time \"%{event.end} %{event.timezone}\" - Duration %{} - Http_resources_accessed %{citrix.netscaler.http_resources_accessed} - NonHttp_services_accessed %{citrix.netscaler.non_http_resources_accessed} - Total_TCP_connections %{citrix.netscaler.total_tcp_connections} - Total_UDP_flows %{citrix.netscaler.total_udp_flows} - Total_policies_allowed %{citrix.netscaler.total_policies_allowed} - Total_policies_denied %{citrix.netscaler.total_policies_denied} - Total_bytes_send %{source.bytes} - Total_bytes_recv %{destination.bytes} - Total_compressedbytes_send %{citrix.netscaler.total_compressed_bytes_send} - Total_compressedbytes_recv %{citrix.netscaler.total_compressed_bytes_recv} - Compression_ratio_send %{} - Compression_ratio_recv %{} - LogoutMethod \"%{event.reason}\" - Group(s) \"%{citrix.netscaler.group}\"",
"if": "ctx?.event?.code == \"sslvpn-logout\"",
"description": "sslvpn-logout-trailer"
}
},
{
"set": {
"description": "copy user.name to user.email",
"if": "ctx?.user?.name != null && ctx.user.name.contains(\"@\")",
"field": "user.email",
"value": "{{user.name}}"
}
},
{
"dissect": {
"description": "parser user.name from email",
"if": "ctx?.user?.name != null && ctx.user.name.contains(\"@\")",
"field": "user.name",
"pattern": "%{user.name}@%{}"
}
},
{
"lowercase": {
"description": "event.reason",
"field": "event.reason",
"ignore_missing": true
}
},
{
"lowercase": {
"description": "citrix.netscaler.status",
"field": "citrix.netscaler.status",
"ignore_missing": true
}
},
{
"lowercase": {
"field": "tls.version_protocol",
"ignore_missing": true,
"description": "tls.version_protocol"
}
},
{
"set": {
"if": "ctx?.citrix?.netscaler?.status != null && ctx.citrix.netscaler.status != \"success\"",
"field": "event.outcome",
"value": "failed"
}
},
{
"remove": {
"description": "drop N/A group",
"if": "ctx?.citrix?.netscaler?.group == \"N/A\"",
"field": "citrix.netscaler.group"
}
},
{
"remove": {
"description": "drop empty user.name",
"if": "ctx?.user?.name != null && ctx.user.name.trim().isEmpty()",
"field": "user.name"
}
},
{
"remove": {
"field": "user.domain",
"if": "ctx?.user?.domain != null && ctx.user.domain.trim().isEmpty()",
"description": "drop empty user.domain"
}
},
{
"date": {
"description": "event.start",
"if": "ctx?.event?.start != null",
"field": "event.start",
"target_field": "event.start",
"formats": [
"MM/dd/yyyy:HH:mm:ss z",
"MM/dd/yyyy:HH:mm:ss"
],
"on_failure": [
{
"remove": {
"field": "event.start"
}
}
]
}
},
{
"date": {
"description": "event.end",
"if": "ctx?.event?.end != null",
"field": "event.end",
"target_field": "event.end",
"formats": [
"MM/dd/yyyy:HH:mm:ss z",
"MM/dd/yyyy:HH:mm:ss"
],
"on_failure": [
{
"remove": {
"field": "event.end"
}
}
]
}
},
{
"script": {
"description": "compute event.duration",
"if": "ctx?.event?.start != null && ctx?.event?.end != null",
"lang": "painless",
"ignore_failure": true,
"source": "ctx.event.duration = Duration.between(Instant.parse(ctx.event.start), Instant.parse(ctx.event.end)).toNanos();\n"
}
},
{
"convert": {
"description": "make destination.bytes a number",
"field": "destination.bytes",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "destination.bytes"
}
}
]
}
},
{
"convert": {
"description": "make destination.port a number",
"field": "destination.port",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "destination.port"
}
}
]
}
},
{
"convert": {
"field": "destination.nat.port",
"type": "long",
"ignore_missing": true,
"description": "make destination.nat.port a number",
"on_failure": [
{
"remove": {
"field": "destination.nat.port"
}
}
]
}
},
{
"convert": {
"description": "make source.bytes a number",
"field": "source.bytes",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "source.bytes"
}
}
]
}
},
{
"convert": {
"description": "make source.port a number",
"field": "source.port",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "source.port"
}
}
]
}
},
{
"convert": {
"field": "source.nat.port",
"type": "long",
"ignore_missing": true,
"description": "make source.nat.port a number",
"on_failure": [
{
"remove": {
"field": "source.nat.port"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.http_resources_accessed a number",
"field": "citrix.netscaler.http_resources_accessed",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.http_resources_accessed"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.non_http_resources_accessed a number",
"field": "citrix.netscaler.non_http_resources_accessed",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.non_http_resources_accessed"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.total_compressed_bytes_recv a number",
"field": "citrix.netscaler.total_compressed_bytes_recv",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.total_compressed_bytes_recv"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.total_compressed_bytes_send a number",
"field": "citrix.netscaler.total_compressed_bytes_send",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.total_compressed_bytes_send"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.total_policies_allowed a number",
"field": "citrix.netscaler.total_policies_allowed",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.total_policies_allowed"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.total_policies_denied a number",
"field": "citrix.netscaler.total_policies_denied",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.total_policies_denied"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.total_tcp_connections a number",
"field": "citrix.netscaler.total_tcp_connections",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.total_tcp_connections"
}
}
]
}
},
{
"convert": {
"description": "make citrix.netscaler.total_udp_flows a number",
"field": "citrix.netscaler.total_udp_flows",
"type": "long",
"ignore_missing": true,
"on_failure": [
{
"remove": {
"field": "citrix.netscaler.total_udp_flows"
}
}
]
}
},
{
"script": {
"description": "compute network.bytes",
"if": "ctx?.source?.bytes != null && ctx?.destination?.bytes != null",
"ignore_failure": true,
"lang": "painless",
"source": "def network = ctx.network;\nif (network == null) {\n network = [:];\n ctx.network = network;\n}\nnetwork.bytes = ctx.source.bytes + ctx.destination.bytes;\n"
}
},
{
"user_agent": {
"field": "user_agent.original",
"ignore_missing": true
}
},
{
"geoip": {
"field": "source.ip",
"target_field": "source.geo",
"ignore_missing": true
}
},
{
"geoip": {
"field": "destination.ip",
"target_field": "destination.geo",
"ignore_missing": true
}
},
{
"geoip": {
"field": "source.ip",
"target_field": "source.as",
"database_file": "GeoLite2-ASN.mmdb",
"properties": [
"asn",
"organization_name"
],
"ignore_missing": true
}
},
{
"geoip": {
"field": "destination.ip",
"target_field": "destination.as",
"database_file": "GeoLite2-ASN.mmdb",
"properties": [
"asn",
"organization_name"
],
"ignore_missing": true
}
},
{
"rename": {
"field": "source.as.asn",
"target_field": "source.as.number",
"ignore_missing": true
}
},
{
"rename": {
"field": "source.as.organization_name",
"target_field": "source.as.organization.name",
"ignore_missing": true
}
},
{
"rename": {
"field": "destination.as.asn",
"target_field": "destination.as.number",
"ignore_missing": true
}
},
{
"rename": {
"field": "destination.as.organization_name",
"target_field": "destination.as.organization.name",
"ignore_missing": true
}
},
{
"dissect": {
"field": "log.source.address",
"pattern": "%{host.ip}:%{}",
"ignore_missing": true,
"ignore_failure": true,
"description": "Extract host.ip from log.source.address"
}
},
{
"script": {
"source": "def commandLine = ctx?.CommandLine;\nif (commandLine != null) {\n commandLine = commandLine.trim();\n if (commandLine != \"\") {\n def args = Arrays.asList(/ /.split(commandLine));\n args.removeIf(arg -> arg == \"\");\n ctx['process'] = new HashMap();\n ctx.process.command_line = commandLine;\n ctx.process.args = args;\n ctx.process.name = args.get(0);\n }\n}",
"if": "ctx?.CommandLine != null",
"description": "Extract process fields from commandline"
}
},
{
"remove": {
"field": "CommandLine",
"ignore_missing": true,
"if": "ctx?.CommandLine != null",
"ignore_failure": true
}
},
{
"set": {
"if": "ctx?.host?.name != null && ctx?.host?.name != \"\"",
"ignore_failure": true,
"field": "observer.hostname",
"value": [
"{{host.name}}"
]
}
},
{
"set": {
"field": "observer.ip",
"value": "{{host.ip}}",
"if": "ctx?.host?.ip != null && ctx?.host?.ip != \"\"",
"ignore_failure": true
}
},
{
"append": {
"field": "related.user",
"value": [
"{{user.name}}"
],
"if": "ctx?.user?.name != null && ctx?.user?.name != \"\"",
"ignore_failure": true
}
},
{
"append": {
"field": "related.ip",
"value": [
"{{source.ip}}"
],
"if": "ctx?.source?.ip != null && ctx?.source?.ip != \"\"",
"ignore_failure": true
}
},
{
"append": {
"field": "related.ip",
"value": [
"{{source.nat.ip}}"
],
"if": "ctx?.source?.nat?.ip != null && ctx?.source?.nat?.ip != \"\"",
"ignore_failure": true
}
},
{
"append": {
"field": "related.ip",
"value": [
"{{destination.ip}}"
],
"if": "ctx?.destination?.ip != null && ctx?.destination?.ip != \"\"",
"ignore_failure": true
}
},
{
"append": {
"field": "related.ip",
"value": [
"{{destination.nat.ip}}"
],
"if": "ctx?.destination?.nat?.ip != null && ctx?.destination?.nat?.ip != \"\"",
"ignore_failure": true
}
},
{
"append": {
"field": "related.hosts",
"value": [
"{{host.name}}"
],
"if": "ctx?.host?.name != null && ctx?.host?.name != \"\"",
"ignore_failure": true
}
},
{
"community_id": {
"ignore_failure": true
}
}
],
"on_failure": [
{
"set": {
"field": "error.message",
"value": "{{ _ingest.on_failure_message }}"
}
}
]
}
Thanks for the awesome pipeline @LaZyDK! Can you confirm exactly which Netscaler product the pipeline covers? There was a rebrand some while ago and I want to ensure we get the integration naming correct. https://www.citrixguru.com/2018/05/08/citrix-rebranding-2018/
Ahh sure. It is the Citrix ADC now. I am happy to help :)
Thanks! That was my first guess, but doubted myself once I saw all the other Netscaler offerings :)
@LaZyDK Thanks for the pipeline enhancements, would you be able to provide some anonymized sample logs that can be used in unit testing this pipeline? I'd like to try to get test coverage over most of the processors to make this maintainable as an integration.
It looks like Netscaler was renamed to Citrix ADC so we'll want our integration to use that naming.
I don't have any sample logs at this time.
Since this seems to be stuck on missing some example logs, here is a good amount of different logs from an ADC:
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default TCP CONN_DELINK 107678819 0 : Source 1.2.3.4:49364 - Vserver 5.6.7.8:443 - NatIP 9.10.11.12:25998 - Destination 13.14.15.16:443 - Delink Time 2022/06/14:16:05:04 - Total_bytes_send 0 - Total_bytes_recv 1212
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default TCP CONN_DELINK 107678821 0 : Source 1.2.3.4:50161 - Vserver 5.6.7.8:443 - NatIP 9.10.11.12:20156 - Destination 13.14.15.16:443 - Delink Time 2022/06/14:16:05:04 - Total_bytes_send 0 - Total_bytes_recv 277
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default TCP CONN_TERMINATE 107678820 0 : Source 1.2.3.4:52689 - Destination 13.14.15.16:443 - Start Time 2022/06/14:16:04:02 - End Time 2022/06/14:16:05:04 - Total_bytes_send 38 - Total_bytes_recv 1
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default TCP CONN_TERMINATE 107678824 0 : Source 1.2.3.4:1134 - Destination 13.14.15.16:443 - Start Time 2022/06/14:16:05:03 - End Time 2022/06/14:16:05:04 - Total_bytes_send 61 - Total_bytes_recv 0
<132> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default AAATM Message 107678832 0 : "SAML: ParseAssertion: Response status success found
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default AAATM Message 107678833 0 : "SAML: successfully verified digest and signature on saml:Response"
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-1 : default AAATM Message 107678834 0 : "SAML : Trying to verify assertion separately"
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-2 : default TCP CONN_TERMINATE 100567496 0 : Source 1.2.3.4:51286 - Destination 13.14.15.16:80 - Start Time 2022/06/14:16:02:40 - End Time 2022/06/14:16:05:04 - Total_bytes_send 1 - Total_bytes_recv 1
<134> 2022/06/14:16:05:04 ADCNAME 0-PPE-2 : default TCP CONN_TERMINATE 100567497 0 : Source 1.2.3.4:51285 - Destination 13.14.15.16:80 - Start Time 2022/06/14:16:02:40 - End Time 2022/06/14:16:05:04 - Total_bytes_send 1 - Total_bytes_recv 1
<134> 2022/06/14:16:07:48 ADCNAME 0-PPE-2 : default SSLVPN HTTPREQUEST 100604596 0 : Context someusername@1.2.3.4 - SessionId: 12690921 - example.domain.com User someusername : Group(s) N/A : Vserver 5.6.7.8:443 - 2022/06/14:16:07:48 : SSO is ON : GET /Citrix/Redacted/URL/Path - -
<134> 2022/06/14:16:07:50 ADCNAME 0-PPE-0 : default API CMD_EXECUTED 48368968 0 : User nsroot - Remote_ip 1.2.3.4 - Command "stat ns" - Status "Success"
<134> 2022/06/14:16:07:48 ADCNAME 0-PPE-2 : default SSLVPN TCPCONNSTAT 100604598 0 : Context someusername@1.2.3.4 - SessionId: 12690921 - User someusername - Client_ip 1.2.3.4 - Nat_ip 9.10.11.12 - Vserver 5.6.7.8:443 - Source 1.2.3.4:60806 - Destination 13.14.15.16:443 - Start_time "2022/06/14:16:07:44 " - End_time "2022/06/14:16:07:48 " - Duration 00:00:04 - Total_bytes_send 0 - Total_bytes_recv 1509 - Total_compressedbytes_send 0 - Total_compressedbytes_recv 0 - Compression_ratio_send 0.00% - Compression_ratio_recv 0.00% - Access Allowed - Group(s) "N/A"
<134> 2022/06/14:16:07:45 ADCNAME 0-PPE-2 : default SSLVPN Message 100603972 0 : "[CGP][ICAUUID=036f6b92-ea91-12a8-9678-7a508f46d78e] App/Desktop launch initiated {client=1.2.3.4:60807}"
<134> 2022/06/14:16:14:10 ADCNAME 0-PPE-1 : default SSLVPN ICASTART 107832863 0 : Source 1.2.3.4:53996 - Destination 13.14.15.16:443 - customername - username:domainname anonymous: - applicationName <REDACTED_APPNAME> - startTime "2022/06/14:16:14:10 " - connectionId 40582742
<134> 2022/06/14:16:14:09 ADCNAME 0-PPE-1 : default SSLVPN Message 107832303 0 : "[CGP][ICAUUID=03f3856b-ec11-12a8-9678-7a508f46d78e] Established connection to VDA successfully {vda=5.6.7.8:444}"
<134> 2022/06/14:16:14:04 ADCNAME 0-PPE-2 : default AAA Message 100697713 0 : "(2-14101845) send_authenticate_pdu: Sending Preamble"
<134> 2022/06/14:16:13:40 ADCNAME 0-PPE-1 : default TCP OTHERCONN_DELINK 107824859 0 : Source 1.2.3.4:32580 - Vserver 5.6.7.8:443 - NatIP 9.10.11.12:8335 - Destination 13.14.15.16:443 - Delink Time 2022/06/14:16:13:40 Total_bytes_send 1914 - Total_bytes_recv 5676
<134> 2022/06/14:16:16:48 ADCNAME 0-PPE-2 : default AAA Message 100740633 0 : "AAA DHT : VPN entry resume notification failed due to ivalid subtype 1"
<131> 2022/06/14:16:16:45 ADCNAME 0-PPE-2 : default SSLVPN Message 100739615 0 : "GwInsight: Func=ns_sslvpn_send_app_launch_record Appflow policy evaluation has failed for SessSeq=d49c63 VPNexportState=7 StatusCode=353"
<134> 2022/06/14:16:18:50 ADCNAME 0-PPE-0 : default SSLVPN LOGOUT 48443905 0 : Context someusername@1.2.3.4 - SessionId: 5472988 - User someusername - Client_ip 1.2.3.4 - Nat_ip "Mapped Ip" - Vserver 5.6.7.8:443 - Start_time "2022/06/14:08:17:38 " - End_time "2022/06/14:16:18:50 " - Duration 08:01:12 - Http_resources_accessed 0 - NonHttp_services_accessed 0 - Total_TCP_connections 27 - Total_UDP_flows 0 - Total_policies_allowed 27 - Total_policies_denied 0 - Total_bytes_send 0 - Total_bytes_recv 26476 - Total_compressedbytes_send 0 - Total_compressedbytes_recv 322 - Compression_ratio_send 0.00% - Compression_ratio_recv 98.78% - LogoutMethod "TimedOut" - Group(s) "N/A"
<134> 2022/06/14:16:18:55 ADCNAME 0-PPE-1 : default SSLVPN LOGIN 107903404 0 : Context someusername@1.2.3.4 - SessionId: 14063303 - User someusername - Client_ip 1.2.3.4 - Nat_ip "Mapped Ip" - Vserver 5.6.7.8:443 - Browser_type "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.115 Safari/537.36" - SSLVPN_client_type ICA - Group(s) "N/A"
<134> 2022/06/14:16:18:18 ADCNAME 0-PPE-2 : default SSLVPN ICAEND_CONNSTAT 100765336 0 : Source 1.2.3.4:54547 - Destination 13.14.15.16:444 - SSLRelayAddress 17.18.19.20:2598 - customername - username:domainname someusername:example.domain.com - startTime "2022/06/14:16:17:51 " - endTime "2022/06/14:16:18:18 " - Duration 00:00:27 - Total_bytes_send 193250 - Total_bytes_recv 36983 - Total_compressedbytes_send 0 - Total_compressedbytes_recv 0 - Compression_ratio_send 0.00% - Compression_ratio_recv 0.00% - connectionId 2812c48 - Total_bytes_wire_send 8028915850309104489 - Total_bytes_wire_recv 8320800952261094732
<134> 2022/06/14:16:14:04 ADCNAME 0-PPE-2 : default AAA EXTRACTED_GROUPS 100697730 0 : Extracted_groups "Really,Long,List,of,Comma,Separated,Groups,with,No,Spaces,between,comma,and,Group,Name,long,enough,to,get,cut,off,by,1024,character,limit,which,is,why,there,is,no,trailing,double,quote,on,this,message
I've sanitized the data, but it should be somewhat in line with what to expect. Let me know if there are any questions or need any additional examples. I tried to provide a good variety of the different logs I see today.
I tried the above ingest logic with data, but getting error with dataset.
Provided Grok expressions do not match field value: ......
Real examples from a Netscaler device (redacted) - ignore the double quotes:
"<134> 07/07/2022:11:21:59 GMT ABCDEF 0-PPE-0 : SSLVPN TCPCONNSTAT 3158907 0 : Context some.name@company.com@10.1.1.1 - SessionId: 111882- User another.email@company.com - Client_ip 10.1.1.1 - Nat_ip 10.2.2.2 - Vserver 10.3.3.3:443 - Source 10.4.4.4:53789 - Destination 10.5.5.5:443 - Start_time \"07/07/2022:11:21:36 GMT\" - End_time \"07/07/2022:11:21:59 GMT\" - Duration 00:00:23 - Total_bytes_send 0 - Total_bytes_recv 725 - Total_compressedbytes_send 0 - Total_compressedbytes_recv 0 - Compression_ratio_send 0.00% - Compression_ratio_recv 0.00% - Access Allowed - Group(s) \"ABC-DEF-USR-TEST-SOME_THING,ABC-DEF-USR-TEST-SOME_THING_ELSE\""
"<134> 07/07/2022:11:22:00 GMT ABCDEF 0-PPE-2 : SSLVPN HTTPREQUEST 6818644 0 : Context another.email@company.com@121.1.1.1- SessionId: 104248- some-domain.company.com User some.email@company.com : Group(s) N/A : Vserver 10.1.2.3:443 - 07/07/2022:11:22:00 GMT POST /Some/Url/Concealed - -"
"<134> 07/07/2022:11:22:00 GMT ABCDEF 0-PPE-2 : SSLVPN TCPCONNSTAT 6818646 0 : Context some.email@company.com@121.1.2.3 - SessionId: 104248- User some.email@company.com - Client_ip 121.2.3.4 - Nat_ip 10.1.1.1 - Vserver 10.1.1.1:443 - Source 10.1.1.1:15591 - Destination 10.1.1.1:443 - Start_time \"07/07/2022:11:21:59 GMT\" - End_time \"07/07/2022:11:22:00 GMT\" - Duration 00:00:01 - Total_bytes_send 0 - Total_bytes_recv 405 - Total_compressedbytes_send 0 - Total_compressedbytes_recv 0 - Compression_ratio_send 0.00% - Compression_ratio_recv 0.00% - Access Allowed - Group(s) \"N/A\""
There are some problems running them against the pipelines proposed here.
On the header, it seems we expect having an hostname twice, while in the sample data we have another token but I do not know the meaning of it (see 0-PPE-2
or 0-PPE-0
above).
The grok
processor "grok citrix header"
:
: SSLVPN TCPCONNSTAT 3158907 0 :
: SSLVPN TCPCONNSTAT 6818646 0 :
: SSLVPN HTTPREQUEST 6818644 0 :
Is expected to have another token after :
, such as:
: X SSLVPN TCPCONNSTAT 3158907 0 :
: X SSLVPN TCPCONNSTAT 6818646 0 :
: X SSLVPN HTTPREQUEST 6818644 0 :
The section SessionId: 104248-
must always have a space after the ID, such as SessionId: 104248 -
The events containing SSLVPN HTTPREQUEST
are:
Vserver 10.1.2.3:443 - 07/07/2022:11:22:00 GMT POST /Some/Url/Concealed - -
But to work, it would need:
Vserver 10.1.2.3:443 - X : SSO is X : POST /Some/Url/Concealed - -
For:
On the header, it seems we expect having an hostname twice, while in the sample data we have another token but I do not know the meaning of it (see 0-PPE-2 or 0-PPE-0 above)
0-PPE-2 or 0-PPE-0
This is the packet engine that processed the request. For my internal Logstash pipeline, I handle this part via grok like:
%{INT}-PPE-%{INT:[netscaler][packet_engine]}
I'm not sure if this is the correct way to do it though.
Hi! We just realized that we haven't looked into this issue in a while. We're sorry! We're labeling this issue as Stale
to make it hit our filters and make sure we get back to it as soon as possible. In the meantime, it'd be extremely helpful if you could take a look at it as well and confirm its relevance. A simple comment with a nice emoji will be enough :+1
. Thank you for your contribution!
👍
Create a new integration for Citrix Netscaler to capture logs.
I started a POC pipeline in https://gist.github.com/andrewkroh/4642be6718ac76bda8e0c0df6aaad1f5. It parses the syslog header and then the common citrix header to determine the message type. Then it uses conditional dissect processor to parse the remainder of the message.
Package / Dataset creation or update checklist
This checklist is intended for Devs which create or update a package to make sure they are consistent.
All Changes
Dashboards
Log datasets
New Packages
References