Add auditlog result field to elasticsearch

Collect and index result values for ssh, http and rest api commands.

Feature: Issue 10228
Change-Id: I86550224886e4117efa2e0c4b57b2cba411951c1
diff --git a/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/AuditEvent.scala b/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/AuditEvent.scala
index 622d68d..d8ab00d 100644
--- a/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/AuditEvent.scala
+++ b/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/AuditEvent.scala
@@ -32,6 +32,7 @@
   def elapsed: Int
   def uuid: String
   def who: Option[Int]
+  def result: String
 
   implicit def formats: Formats = DefaultFormats
 
@@ -50,7 +51,8 @@
   timeAtStart: Long,
   what: String,
   elapsed: Int,
-  uuid: String
+  uuid: String,
+  result: String
 ) extends AuditEvent {
 
   override val auditType = SshAuditEvent.auditType
@@ -69,20 +71,20 @@
       timeAtStart(jsEvent),
       what(jsEvent),
       elapsed(jsEvent),
-      uuid(jsEvent)
+      uuid(jsEvent),
+      sshResult(jsEvent)
     )
   }
 }
 
 sealed trait BaseHttpAuditEvent extends AuditEvent {
   def httpMethod: String
-  def httpStatus: Int
 }
 
 final case class HttpAuditEvent(
   accessPath: Option[String],
   httpMethod: String,
-  httpStatus: Int,
+  result: String,
   sessionId: String,
   who: Option[Int],
   timeAtStart: Long,
@@ -101,7 +103,7 @@
     HttpAuditEvent(
       accessPath(jsEvent),
       httpMethod(jsEvent),
-      httpStatus(jsEvent),
+      httpResult(jsEvent),
       sessionId(jsEvent),
       who(jsEvent),
       timeAtStart(jsEvent),
@@ -115,7 +117,7 @@
 final case class ExtendedHttpAuditEvent(
   accessPath: Option[String],
   httpMethod: String,
-  httpStatus: Int,
+  result: String,
   sessionId: String,
   who: Option[Int],
   timeAtStart: Long,
@@ -133,7 +135,7 @@
     ExtendedHttpAuditEvent(
       accessPath(jsEvent),
       httpMethod(jsEvent),
-      httpStatus(jsEvent),
+      httpResult(jsEvent),
       sessionId(jsEvent),
       who(jsEvent),
       timeAtStart(jsEvent),
diff --git a/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/ElasticSearchFields.scala b/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/ElasticSearchFields.scala
index 2721074..41d33ec 100644
--- a/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/ElasticSearchFields.scala
+++ b/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/ElasticSearchFields.scala
@@ -21,6 +21,7 @@
   val USER_IDENTIFIER_FIELD = "user_identifier"
   val AUDIT_TYPE_FIELD      = "audit_type"
   val ACCESS_PATH_FIELD     = "access_path"
+  val RESULT_FIELD          = "result"
 
   val FACETING_FIELDS = List(
     TIME_BUCKET_FIELD,
@@ -28,7 +29,8 @@
     USER_IDENTIFIER_FIELD,
     ACCESS_PATH_FIELD,
     COMMAND_FIELD,
-    COMMAND_ARGS_FIELD
+    COMMAND_ARGS_FIELD,
+    RESULT_FIELD
   )
 
   val NUM_EVENTS_FIELD = "num_events"
diff --git a/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/json/AuditLogFieldExtractors.scala b/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/json/AuditLogFieldExtractors.scala
index 73da840..8c2a9a0 100644
--- a/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/json/AuditLogFieldExtractors.scala
+++ b/auditlog/src/main/scala/com/gerritforge/analytics/auditlog/model/json/AuditLogFieldExtractors.scala
@@ -27,6 +27,7 @@
   val uuid        = (jsEvent: JValue) => (jsEvent \ "uuid" \ "uuid").extract[String]
   val who         = (jsEvent: JValue) => (jsEvent \ "who" \ "account_id" \ "id").extractOpt[Int]
   val httpMethod  = (jsEvent: JValue) => (jsEvent \ "http_method").extract[String]
-  val httpStatus  = (jsEvent: JValue) => (jsEvent \ "http_status").extract[Int]
+  val httpResult  = (jsEvent: JValue) => (jsEvent \ "http_status").extract[String]
+  val sshResult   = (jsEvent: JValue) => (jsEvent \ "result").extract[String]
 
 }
diff --git a/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/AuditLogsTransformerSpec.scala b/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/AuditLogsTransformerSpec.scala
index dcc9f92..aade9f9 100644
--- a/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/AuditLogsTransformerSpec.scala
+++ b/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/AuditLogsTransformerSpec.scala
@@ -41,6 +41,7 @@
         anonymousHttpAuditEvent.accessPath.get,
         GIT_UPLOAD_PACK,
         anonymousHttpAuditEvent.what,
+        anonymousHttpAuditEvent.result,
         expectedAggregatedCount
     )
   }
@@ -60,6 +61,7 @@
       authenticatedHttpAuditEvent.accessPath.get,
       GIT_UPLOAD_PACK,
       authenticatedHttpAuditEvent.what,
+      authenticatedHttpAuditEvent.result,
       expectedAggregatedCount
     )
   }
@@ -82,6 +84,7 @@
       authenticatedHttpAuditEvent.accessPath.get,
       GIT_UPLOAD_PACK,
       authenticatedHttpAuditEvent.what,
+      authenticatedHttpAuditEvent.result,
       expectedAggregatedCount
     )
   }
@@ -101,6 +104,7 @@
       sshAuditEvent.accessPath.get,
       SSH_GERRIT_COMMAND,
       SSH_GERRIT_COMMAND_ARGUMENTS,
+      sshAuditEvent.result,
       expectedAggregatedCount
     )
   }
@@ -120,6 +124,7 @@
       sshAuditEvent.accessPath.get,
       SSH_GERRIT_COMMAND,
       SSH_GERRIT_COMMAND_ARGUMENTS,
+      sshAuditEvent.result,
       expectedAggregatedCount
     )
   }
@@ -141,6 +146,7 @@
         sshAuditEvent.accessPath.get,
         SSH_GERRIT_COMMAND,
         SSH_GERRIT_COMMAND_ARGUMENTS,
+        sshAuditEvent.result,
         expectedAggregatedCount
       ),
       Row(
@@ -150,6 +156,7 @@
         sshAuditEvent.accessPath.get,
         SSH_GERRIT_COMMAND,
         SSH_GERRIT_COMMAND_ARGUMENTS,
+        sshAuditEvent.result,
         expectedAggregatedCount
       )
     )
@@ -172,6 +179,7 @@
         sshAuditEvent.accessPath.get,
         SSH_GERRIT_COMMAND,
         SSH_GERRIT_COMMAND_ARGUMENTS,
+        sshAuditEvent.result,
         expectedSshAggregatedCount
       ),
       Row(
@@ -181,6 +189,7 @@
         authenticatedHttpAuditEvent.accessPath.get,
         GIT_UPLOAD_PACK,
         authenticatedHttpAuditEvent.what,
+        authenticatedHttpAuditEvent.result,
         expectedHttpAggregatedCount
       )
     )
diff --git a/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/TestFixtures.scala b/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/TestFixtures.scala
index 02dad6a..7c5b65e 100644
--- a/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/TestFixtures.scala
+++ b/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/TestFixtures.scala
@@ -27,7 +27,7 @@
   val GIT_UPLOAD_PACK = "git-upload-pack"
 
   val httpMethod = "GET"
-  val httpStatus = 200
+  val httpStatus = "200"
 
   val httpWhat=s"https://review.gerrithub.io/Mirantis/tcp-qa/$GIT_UPLOAD_PACK"
 
@@ -35,10 +35,11 @@
   val authenticatedHttpAuditEvent: HttpAuditEvent = anonymousHttpAuditEvent.copy(who=Some(userId))
 
   val sshAccessPath  = "SSH_COMMAND"
+  val sshResult = "0"
   val SSH_GERRIT_COMMAND = "gerrit"
   val SSH_GERRIT_COMMAND_ARGUMENTS = "stream-events.-s.patchset-created.-s.change-restored.-s.comment-added"
 
   val sshWhat        = s"$SSH_GERRIT_COMMAND.$SSH_GERRIT_COMMAND_ARGUMENTS"
 
-  val sshAuditEvent = SshAuditEvent(Some(sshAccessPath), sessionId, Some(userId), timeAtStart, sshWhat, elapsed, uuid)
+  val sshAuditEvent = SshAuditEvent(Some(sshAccessPath), sessionId, Some(userId), timeAtStart, sshWhat, elapsed, uuid, sshResult)
 }
diff --git a/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/model/AuditEventSpec.scala b/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/model/AuditEventSpec.scala
index 33911f0..1b4bf80 100644
--- a/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/model/AuditEventSpec.scala
+++ b/auditlog/src/test/scala/com/gerritforge/analytics/auditlog/model/AuditEventSpec.scala
@@ -40,7 +40,7 @@
   "A json representing an http audit event log" should "be parsed into a success of HttpAuditEvent" in {
 
     val httpMethod = "POST"
-    val httpStatus = 200
+    val httpStatus = "200"
     val sessionId  = "1r7ywi4vd3jk410dv60pvd19vk"
     val accountId  = 1009124
     val accessPath = "GIT"
@@ -107,6 +107,7 @@
     val what        = "gerrit.stream-events.-s.patchset-created.-s.change-restored.-s.comment-added"
     val elapsed     = 12
     val auditUUID   = "audit:dd74e098-9260-4720-9143-38a0a0a5e500"
+    val sshResult     = "0"
     val jsonEvent =
       s"""
          |{
@@ -123,7 +124,7 @@
          |    "when": $timeAtStart,
          |    "what": "$what",
          |    "params": {},
-         |    "result": "0",
+         |    "result": "$sshResult",
          |    "time_at_start": $timeAtStart,
          |    "elapsed": $elapsed,
          |    "uuid": {
@@ -134,7 +135,7 @@
        """.stripMargin
 
     inside (AuditEvent.parseRaw(jsonEvent).success.value) {
-      case SshAuditEvent(gotAccessPath, gotSessionId, gotWho, gotTimeAtStart, gotWhat, gotElapsed, gotUUID) =>
+      case SshAuditEvent(gotAccessPath, gotSessionId, gotWho, gotTimeAtStart, gotWhat, gotElapsed, gotUUID, gotResult) =>
         gotSessionId   shouldBe sessionId
         gotWho         should contain(accountId)
         gotTimeAtStart shouldBe timeAtStart
@@ -142,6 +143,7 @@
         gotElapsed     shouldBe elapsed
         gotUUID        shouldBe auditUUID
         gotAccessPath  should contain(accessPath)
+        gotResult      shouldBe sshResult
     }
   }
 
@@ -152,6 +154,7 @@
     val what        = "AUTH"
     val elapsed     = 0
     val auditUUID   = "audit:8d40c495-7b51-4003-81f2-718bc04addf3"
+    val failedResult = "FAIL"
     val jsonEvent =
       s"""
          |{
@@ -161,7 +164,7 @@
          |    "when": 1542240154088,
          |    "what": "$what",
          |    "params": {},
-         |    "result": "FAIL",
+         |    "result": "$failedResult",
          |    "time_at_start": $timeAtStart,
          |    "elapsed": $elapsed,
          |    "uuid": {
@@ -172,7 +175,7 @@
        """.stripMargin
 
     inside (AuditEvent.parseRaw(jsonEvent).success.value) {
-      case SshAuditEvent(gotAccessPath, gotSessionId, gotWho, gotTimeAtStart, gotWhat, gotElapsed, gotUUID) =>
+      case SshAuditEvent(gotAccessPath, gotSessionId, gotWho, gotTimeAtStart, gotWhat, gotElapsed, gotUUID, gotResult) =>
         gotSessionId   shouldBe sessionId
         gotWho         shouldBe empty
         gotTimeAtStart shouldBe timeAtStart
@@ -180,13 +183,14 @@
         gotElapsed     shouldBe elapsed
         gotUUID        shouldBe auditUUID
         gotAccessPath  shouldBe empty
+        gotResult shouldBe failedResult
     }
   }
 
   "A json representing an extended http audit event log" should "be parsed into a success of ExtendedHttpAuditEvent" in {
 
     val httpMethod  = "GET"
-    val httpStatus  = 200
+    val httpStatus  = "200"
     val sessionId   = "aQ3Dprttdq3tT25AMDHhF7zKpMOph64XnW"
     val accountId   = 1011373
     val accessPath  = "REST_API"
@@ -222,13 +226,13 @@
        """.stripMargin
 
     inside (AuditEvent.parseRaw(jsonEvent).success.value) {
-      case ExtendedHttpAuditEvent(gotAccessPath,gotHttpMethod,gotHttpStatus,gotSessionId,gotWho,gotTimeAtStart,gotWhat,gotElapsed,gotUUID) =>
+      case ExtendedHttpAuditEvent(gotAccessPath,gotHttpMethod,gotHttpResult,gotSessionId,gotWho,gotTimeAtStart,gotWhat,gotElapsed,gotUUID) =>
         gotSessionId   shouldBe sessionId
         gotWho         should   contain(accountId)
         gotTimeAtStart shouldBe timeAtStart
         gotHttpMethod  shouldBe httpMethod
         gotWhat        shouldBe what
-        gotHttpStatus  shouldBe httpStatus
+        gotHttpResult  shouldBe httpStatus
         gotElapsed     shouldBe elapsed
         gotUUID        shouldBe auditUUID
         gotAccessPath  should   contain(accessPath)
@@ -240,7 +244,7 @@
   "an HttpAuditEvent" should "be serializable into json" in {
 
     val httpMethod = "GET"
-    val httpStatus = 200
+    val httpStatus = "200"
     val sessionId = "someSessionId"
     val accessPath = "GIT"
     val timeAtStart = 1000L
@@ -256,7 +260,7 @@
       ("access_path" -> accessPath) ~
       ("time_at_start" -> timeAtStart) ~
       ("http_method" -> httpMethod) ~
-      ("http_status" -> httpStatus) ~
+      ("result" -> httpStatus) ~
       ("what" -> what) ~
       ("elapsed" -> elapsed) ~
       ("uuid" -> uuid) ~
@@ -268,7 +272,7 @@
   "an ExtendedHttpAuditEvent" should "be serializable into json" in {
 
     val httpMethod = "GET"
-    val httpStatus = 200
+    val httpStatus = "200"
     val accessPath = "REST_API"
     val sessionId = "someSessionId"
     val accountId = 123
@@ -285,7 +289,7 @@
       ("access_path" -> accessPath) ~
       ("time_at_start" -> timeAtStart) ~
       ("http_method" -> httpMethod) ~
-      ("http_status" -> httpStatus) ~
+      ("result" -> httpStatus) ~
       ("what" -> what) ~
       ("elapsed" -> elapsed) ~
       ("uuid" -> uuid) ~
@@ -302,9 +306,10 @@
     val timeAtStart = 1542240322369L
     val what        = "gerrit.stream-events.-s.patchset-created.-s.change-restored.-s.comment-added"
     val elapsed     = 12
-    val uuid   = "audit:dd74e098-9260-4720-9143-38a0a0a5e500"
+    val uuid        = "audit:dd74e098-9260-4720-9143-38a0a0a5e500"
+    val sshResult   = "0"
 
-    val event = SshAuditEvent(Some(accessPath), sessionId, Some(accountId), timeAtStart, what, elapsed, uuid)
+    val event = SshAuditEvent(Some(accessPath), sessionId, Some(accountId), timeAtStart, what, elapsed, uuid, sshResult)
 
     val expectedJson: JValue =
       ("session_id" -> sessionId) ~
@@ -314,7 +319,8 @@
       ("what" -> what) ~
       ("elapsed" -> elapsed) ~
       ("uuid" -> uuid) ~
-      ("audit_type" -> sshAuditEvent)
+      ("audit_type" -> sshAuditEvent) ~
+      ("result" -> sshResult)
 
     parse(event.toJsonString) shouldBe expectedJson
   }