@@ -7,8 +7,8 @@ import akka.NotUsed
7
7
import akka .stream .Materializer
8
8
import akka .stream .scaladsl .Source
9
9
import org .elastic4play .models .BaseModelDef
10
- import org .elastic4play .services ._
11
10
import org .elastic4play .services .JsonFormat .attachmentFormat
11
+ import org .elastic4play .services ._
12
12
import org .elastic4play .utils
13
13
import org .elastic4play .utils .{ Hasher , RichJson }
14
14
import play .api .libs .json .JsValue .jsValueToJsLookup
@@ -164,26 +164,47 @@ class Migration(
164
164
Operation ((f : String ⇒ Source [JsObject , NotUsed ]) ⇒ {
165
165
case " alert" ⇒ f(" alert" ).flatMapConcat { alert ⇒
166
166
val artifactsAndData = Future .traverse((alert \ " artifacts" ).asOpt[List [JsObject ]].getOrElse(Nil )) { artifact ⇒
167
- (artifact \ " data" ).asOpt[String ]
168
- .collect {
169
- case AlertSrv .dataExtractor(filename, contentType, data @ Base64 (rawData)) ⇒
170
- val attachmentId = mainHasher.fromByteArray(rawData).head.toString()
171
- ds.getEntity(datastoreName, s " ${attachmentId}_0 " )
172
- .map(_ ⇒ Nil )
173
- .recover {
174
- case _ if containsOrAdd(attachmentId) ⇒ Nil
175
- case _ ⇒
176
- Seq (Json .obj(
177
- " _type" → datastoreName,
178
- " _id" → s " ${attachmentId}_0 " ,
179
- " data" → data))
180
- }
181
- .map { dataEntity ⇒
182
- val attachment = Attachment (filename, extraHashers.fromByteArray(rawData), rawData.length.toLong, contentType, attachmentId)
183
- (artifact - " data" + (" attachment" → Json .toJson(attachment))) → dataEntity
167
+ val isFile = (artifact \ " dataType" ).asOpt[String ].contains(" file" )
168
+ // get MISP attachment
169
+ if (! isFile)
170
+ Future .successful(artifact → Nil )
171
+ else {
172
+ (for {
173
+ dataStr ← (artifact \ " data" ).asOpt[String ]
174
+ dataJson ← Try (Json .parse(dataStr)).toOption
175
+ dataObj ← dataJson.asOpt[JsObject ]
176
+ filename ← (dataObj \ " filename" ).asOpt[String ].map(_.split(" |" ).head)
177
+ attributeId ← (dataObj \ " attributeId" ).asOpt[String ]
178
+ attributeType ← (dataObj \ " attributeType" ).asOpt[String ]
179
+ } yield Future .successful((artifact - " data" + (" remoteAttachment" → Json .obj(
180
+ " reference" → attributeId,
181
+ " filename" → filename,
182
+ " type" → attributeType))) → Nil ))
183
+ .orElse {
184
+ (artifact \ " data" ).asOpt[String ]
185
+ .collect {
186
+ // get attachment encoded in data field
187
+ case AlertSrv .dataExtractor(filename, contentType, data @ Base64 (rawData)) ⇒
188
+ val attachmentId = mainHasher.fromByteArray(rawData).head.toString()
189
+ ds.getEntity(datastoreName, s " ${attachmentId}_0 " )
190
+ .map(_ ⇒ Nil )
191
+ .recover {
192
+ case _ if containsOrAdd(attachmentId) ⇒ Nil
193
+ case _ ⇒
194
+ Seq (Json .obj(
195
+ " _type" → datastoreName,
196
+ " _id" → s " ${attachmentId}_0 " ,
197
+ " data" → data))
198
+ }
199
+ .map { dataEntity ⇒
200
+ val attachment = Attachment (filename, extraHashers.fromByteArray(rawData), rawData.length.toLong, contentType, attachmentId)
201
+ (artifact - " data" + (" attachment" → Json .toJson(attachment))) → dataEntity
202
+ }
184
203
}
185
- }
186
- .getOrElse(Future .successful(artifact → Nil ))
204
+
205
+ }
206
+ .getOrElse(Future .successful(artifact → Nil ))
207
+ }
187
208
}
188
209
Source .fromFuture(artifactsAndData)
189
210
.mapConcat { ad ⇒
@@ -206,6 +227,12 @@ class Migration(
206
227
dblist + (" value" → value)
207
228
}
208
229
case other ⇒ other
230
+ },
231
+ // Add empty metrics and custom fields in cases
232
+ mapEntity(" case" ) { caze ⇒
233
+ val metrics = (caze \ " metrics" ).asOpt[JsObject ].getOrElse(JsObject (Nil ))
234
+ val customFields = (caze \ " customFields" ).asOpt[JsObject ].getOrElse(JsObject (Nil ))
235
+ caze + (" metrics" → metrics) + (" customFields" → customFields)
209
236
})
210
237
}
211
238
0 commit comments