Skip to content

Commit

Permalink
Merge branch 'release/2.11.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
nadouani committed May 24, 2017
2 parents 0212416 + b7320c2 commit f7b0ce8
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 53 deletions.
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
# Change Log

## [2.11.1](https://github.com/CERT-BDF/TheHive/tree/HEAD) (2017-05-17)
## [2.11.2](https://github.com/CERT-BDF/TheHive/tree/2.11.2)
[Full Changelog](https://github.com/CERT-BDF/TheHive/compare/2.11.1...2.11.2)

**Implemented enhancements:**

- Visually distinguish between analyzed and non analyzer observables [\#224](https://github.com/CERT-BDF/TheHive/issues/224)
- Add Description Field to Alert Preview Modal [\#218](https://github.com/CERT-BDF/TheHive/issues/218)
- Show case severity in lists [\#188](https://github.com/CERT-BDF/TheHive/issues/188)

**Fixed bugs:**

- MISP synchronization - attributes are not retrieve [\#221](https://github.com/CERT-BDF/TheHive/issues/221)
- MISP synchronization - Alerts are wrongly updated [\#220](https://github.com/CERT-BDF/TheHive/issues/220)
- Cortex jobs from thehive fail silently [\#219](https://github.com/CERT-BDF/TheHive/issues/219)

**Merged pull requests:**

- Fixing links to docu repo [\#213](https://github.com/CERT-BDF/TheHive/pull/213) ([SHSauler](https://github.com/SHSauler))

## [2.11.1](https://github.com/CERT-BDF/TheHive/tree/2.11.1) (2017-05-17)
[Full Changelog](https://github.com/CERT-BDF/TheHive/compare/2.11.0...2.11.1)

**Implemented enhancements:**
Expand Down
37 changes: 37 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
TheHive is a scalable 3-in-1 open source and free security incident response platform designed to make life easier for SOCs, CSIRTs, CERTs and any information security practitioner dealing with security incidents that need to be investigated and acted upon swiftly.

## Hardware Pre-requisites

TheHive uses ElasticSearch to store data. Both software use a Java VM. We recommend using a virtual machine with 8vCPU, 8
GB of RAM and 60 GB of disk. You can also use a physical machine with similar specifications.

## What's New?

- [Changelog](/CHANGELOG.md)
- [Migration guide](migration-guide.md)

## Installation Guides

TheHive can be installed using:
- An [RPM package](installation/rpm-guide.md)
- A [DEB package](installation/deb-guide.md)
- [Docker](installation/docker-guide.md)
- [Binary](installation/binary-guide.md)
- [Ansible script](https://github.com/drewstinnett/ansible-thehive) contributed by
[@drewstinnett](https://github.com/drewstinnett)

TheHive can also be [built from sources](installation/build-guide.md).

## Administration Guides

- [Administrator's guide](admin/admin-guide.md)
- [Configuration guide](admin/configuration.md)
- [Updating](admin/updating.md)
- [Backup & Restore](admin/backup-restore.md)

## Developer Guides

- [API documentation](api/README.md)

## Other
- [FAQ](FAQ.md)
19 changes: 19 additions & 0 deletions docs/installation/rpm-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Installing TheHive Using an RPM Package

TheHive's RPM packages are published on our Bintray repository. All packages are PGP signed using the key which ID is [562CBC1C](/PGP-PUBLIC-KEY). The key's fingerprint is:

```0CD5 AC59 DE5C 5A8E 0EE1 3849 3D99 BB18 562C BC1C```

To intall TheHive from an RPM package, you'll need to begin by installing the RPM release package using the following command:
```
yum install install https://dl.bintray.com/cert-bdf/rpm/thehive-project-release-1.0.0-3.noarch.rpm
```
This will install TheHive Project's repository in `/etc/yum.repos.d/thehive-rpm.repo` and the GPG public key `in
/etc/pki/rpm-gpg/GPG-TheHive-Project`.

Once done, you will able to install TheHive package using yum:
```
yum install thehive
```

One installed, you should [install ElasticSearch](elasticsearch-guide.md) and [configure TheHive](../admin/configuration.md).
2 changes: 1 addition & 1 deletion package/debian/postinst
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ addUser thehive "" thehive "thehive daemon-user" "/bin/false"
chown thehive:thehive /var/log/thehive
chown root:thehive /etc/thehive/application.conf /etc/thehive/logback.xml
chmod 0640 /etc/thehive/application.conf /etc/thehive/logback.xml
mkdir /opt/thehive/conf
mkdir -p /opt/thehive/conf
4 changes: 3 additions & 1 deletion thehive-misp/app/connectors/misp/JsonFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ object JsonFormat {
publishTimestamp (json \ "publish_timestamp").validate[String]
publishDate = new Date(publishTimestamp.toLong * 1000)
threatLevel (json \ "threat_level_id").validate[String]
isPublished (json \ "published").validate[Boolean]
} yield MispAlert(
org,
eventId,
date,
publishDate,
isPublished,
s"#$eventId ${info.trim}",
s"Imported from MISP Event #$eventId, created at $date",
threatLevel.toLong,
Expand All @@ -43,7 +45,7 @@ object JsonFormat {
"")
}

implicit val mispAlertWrites: Writes[MispAlert] = Json.writes[MispAlert]
implicit val mispAlertWrites: Writes[MispAlert] = Json.writes[MispAlert].transform((_: JsValue).asInstanceOf[JsObject] - "isPublished")

implicit val attributeReads: Reads[MispAttribute] = Reads(json
for {
Expand Down
1 change: 1 addition & 0 deletions thehive-misp/app/connectors/misp/MispModel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ case class MispAlert(
sourceRef: String,
date: Date,
lastSyncDate: Date,
isPublished: Boolean,
title: String,
description: String,
severity: Long,
Expand Down
35 changes: 23 additions & 12 deletions thehive-misp/app/connectors/misp/MispSrv.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ case class MispConnection(

private[MispConnection] lazy val logger = Logger(getClass)

logger.info(s"Add MISP connection $name ($baseUrl)\n\tproxy configuration: ${ws.proxy}")
logger.info(
s"""Add MISP connection $name
|\turl: $baseUrl
|\tproxy: ${ws.proxy}
|\tcase template: ${caseTemplate.getOrElse("<not set>")}
|\tartifact tags: ${artifactTags.mkString}""".stripMargin)

private[misp] def apply(url: String) =
ws.url(s"$baseUrl/$url")
Expand Down Expand Up @@ -165,19 +170,21 @@ class MispSrv @Inject() (
// get related alert
.mapAsyncUnordered(1) {
case (mcfg, lastSyncDate, event)
logger.trace(s"Looking for alert misp:${event.source}:${event.sourceRef}")
alertSrv.get("misp", event.source, event.sourceRef)
.map(a (mcfg, lastSyncDate, event, a))
}
.mapAsyncUnordered(1) {
case (mcfg, lastSyncDate, event, alert)
logger.trace(s"MISP synchro ${mcfg.name} last sync at $lastSyncDate, event ${event.sourceRef}, alert ${alert.fold("no alert")("alert" + _.alertId())}")
logger.info(s"getting MISP event ${event.sourceRef}")
getAttributes(mcfg, event.sourceRef, Some(lastSyncDate))
getAttributes(mcfg, event.sourceRef, alert.map(_ lastSyncDate))
.map((mcfg, event, alert, _))
}
.mapAsyncUnordered(1) {
// if there is no related alert, create a new one
case (mcfg, event, None, attrs)
logger.info(s"MISP event ${event.sourceRef} has no related alert, create it")
logger.info(s"MISP event ${event.sourceRef} has no related alert, create it with ${attrs.size} observable(s)")
val alertJson = Json.toJson(event).as[JsObject] +
("type" JsString("misp")) +
("caseTemplate" mcfg.caseTemplate.fold[JsValue](JsNull)(JsString)) +
Expand All @@ -188,11 +195,12 @@ class MispSrv @Inject() (

// if a related alert exists, update it
case (_, event, Some(alert), attrs)
logger.info(s"MISP event ${event.sourceRef} has related alert, update it")
logger.info(s"MISP event ${event.sourceRef} has related alert, update it with ${attrs.size} observable(s)")
val alertJson = Json.toJson(event).as[JsObject] -
"type" -
"source" -
"sourceRef" -
"caseTemplate" -
"date" +
("artifacts" JsArray(attrs)) +
("status" (if (!alert.follow()) Json.toJson(alert.status())
Expand Down Expand Up @@ -232,14 +240,17 @@ class MispSrv @Inject() (
logger.warn(s"Invalid MISP event format:\n${response.body}")
Nil
}
val events = eventJson.flatMap { j
j.asOpt[MispAlert]
.map(_.copy(source = mispConnection.name))
.orElse {
logger.warn(s"MISP event can't be parsed\n$j")
None
}
}
val events = eventJson
.flatMap { j
j.asOpt[MispAlert]
.map(_.copy(source = mispConnection.name))
.orElse {
logger.warn(s"MISP event can't be parsed\n$j")
None
}
}
.filter(event event.isPublished && event.date.after(fromDate))

val eventJsonSize = eventJson.size
val eventsSize = events.size
if (eventJsonSize != eventsSize)
Expand Down
3 changes: 2 additions & 1 deletion ui/app/styles/case.css
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ table.case-list .case-tags {
font-size: 12px !important;
}

table.case-list .case-tags .label {
table.case-list .case-tags .label,
.case-tags .label {
font-size: inherit !important;
font-weight: normal;
}
66 changes: 36 additions & 30 deletions ui/app/views/partials/alert/event.dialog.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="modal-header bg-primary">
<h3 class="modal-title">Alert Preview</h3>
<h3 class="modal-title">Alert Preview <span class="label label-default" ng-class="{'label-danger': dialog.event.status==='New', 'label-warning': dialog.event.status === 'Updated'}">{{dialog.event.status}}</span></h3>
</div>
<div class="modal-body">

Expand All @@ -12,36 +12,42 @@ <h3 class="modal-title">Alert Preview</h3>
<div class="row" ng-hide="dialog.loading">
<div class="col-md-12">
<div class="alert-details">
<h4 class="vpad10 text-primary">
Basic details
<span class="label label-default pull-right" ng-class="{'label-danger': dialog.event.status==='New', 'label-warning': dialog.event.status === 'Updated'}">{{dialog.event.status}}</span>
<h4 class="text-primary">
<severity value="dialog.event.severity"></severity>
<span>{{dialog.event.title}}</span>
</h4>
<dl class="dl-horizontal clear">
<dt>Reference</dt>
<dd>{{dialog.event.sourceRef}}</dd>
</dl>
<dl class="dl-horizontal clear">
<dt>Title</dt>
<dd>
<severity value="dialog.event.severity"></severity>{{dialog.event.title}}</dd>
</dl>
<dl class="dl-horizontal clear">
<dt>Date</dt>
<dd>{{dialog.event.date | showDate}}</dd>
</dl>
<dl class="dl-horizontal clear">
<dt>Source</dt>
<dd>{{dialog.event.source}}</dd>
</dl>
<dl class="dl-horizontal clear">
<dt>Tags</dt>
<dd>
<div class="flexwrap mt-xxs">
<strong class="text-muted mr-xxxs" ng-if="!dialog.event.tags || dialog.event.tags === 0">None</strong>
<span ng-repeat="tag in dialog.event.tags track by $index" class="label label-primary mb-xxxs mr-xxxs">{{tag}}</span>
</div>
</dd>
</dl>
<div class="mt-xxs">
<span>
<strong><i class="fa fa-calendar"></i> Date: </strong>
<span>{{dialog.event.date | showDate}}</span>
</span>
<span class="ml-xxs">
<strong><i class="fa fa-certificate"></i> Type: </strong>
<span>{{dialog.event.type}}</span>
</span>
<span class="ml-xxs">
<strong><i class="fa fa-barcode"></i> Reference: </strong>
<span>{{dialog.event.sourceRef}}</span>
</span>
<span class="ml-xxs">
<strong><i class="fa fa-bullseye"></i> Source: </strong>
<span>{{dialog.event.source}}</span>
</span>
</div>
<div class="case-tags flexwrap mt-xxs">
<strong><i class="fa fa-tags mr-xxxs"></i></strong>
<strong class="text-muted mr-xxxs" ng-if="!dialog.event.tags || dialog.event.tags === 0">None</strong>
<span ng-repeat="tag in dialog.event.tags track by $index" class="label label-primary mb-xxxs mr-xxxs">{{tag}}</span>
</div>

<div class="mt-xs" ng-if="dialog.event.description">
<h4 class="vpad10 text-primary">
Description
</h4>
<div>
<div marked="dialog.event.description" class="markdown"></div>
</div>
</div>
</div>

<div class="alert-artifacts" ng-if="dialog.event.artifacts.length > 0">
Expand Down
6 changes: 5 additions & 1 deletion ui/app/views/partials/index-mytasks.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<psearch control="list"></psearch>

<table class="table table-striped table-hover valigned">
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="text-center" style="width: 60px;">Severity</th>
<th>Task</th>
<th width="250px;">Date</th>
</tr>
Expand All @@ -13,6 +14,9 @@
ng-repeat="value in list.values"
ng-class="{'warning': (value.flag == true)}"
ng-click="openEntity(value)">
<td class="text-center">
<severity active="false" value="value.case.severity"></severity>
</td>
<td>
<div>
<span ng-if="value.flag"><i class="text-primary glyphicon glyphicon-flag"></i></span>
Expand Down
6 changes: 5 additions & 1 deletion ui/app/views/partials/index-waitingtasks.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<psearch control="list"></psearch>

<table class="table table-striped table-hover valigned">
<table class="table table-striped table-hover">
<thead>
<tr>
<th class="text-center" style="width: 60px;">Severity</th>
<th>Task</th>
<th width="100px;">Action</th>
</tr>
Expand All @@ -11,6 +12,9 @@
<tbody>
<tr class="task-row"
ng-repeat="value in list.values">
<td class="text-center">
<severity active="false" value="value.case.severity"></severity>
</td>
<td>
<div>{{value.title}}</div>
<div>
Expand Down
11 changes: 9 additions & 2 deletions ui/app/views/partials/observables/list/artifacts-list-main.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ <h4>List of observables ({{artifacts.total || 0}} of {{artifactStats.count}})</h
<th style="width: 15px"></th>
<th style="width: 100px">Type <a href ng-click="artifacts.sort='-dataType'; artifacts.update()"><i class="fa fa-caret-up"></i></a><a href ng-click="artifacts.sort='+dataType'; artifacts.update()"><i class="fa fa-caret-down"></i></a></th>
<th>Data/Filename <a href ng-click="artifacts.sort='-data'; artifacts.update()"><i class="fa fa-caret-up"></i></a><a href ng-click="artifacts.sort='+data'; artifacts.update()"><i class="fa fa-caret-down"></i></a></th>
<th style="width: 400px">Analysis</th>
<th style="width: 200px">Analysis</th>
<th style="width: 120px">Date added <a href ng-click="artifacts.sort='-startDate'; artifacts.update()"><i class="fa fa-caret-up"></i></a><a href ng-click="artifacts.sort='+startDate'; artifacts.update()"><i class="fa fa-caret-down"></i></a></th>
</tr>
</thead>
Expand Down Expand Up @@ -77,7 +77,14 @@ <h4>List of observables ({{artifacts.total || 0}} of {{artifactStats.count}})</h
</div>
</td>
<td>
<ng-pluralize count="keys(artifact.reports).length" when="{'0': 'No reports available', 'one': '1 report available', 'other': '{} reports available'}"></ng-pluralize>
<div ng-show="keys(artifact.reports).length === 0" class="text-muted">
<em>No reports available</em>
</div>
<div ng-show="keys(artifact.reports).length > 0">
<span class="badge">{{keys(artifact.reports).length}}</span>
<ng-pluralize count="keys(artifact.reports).length" when="{'one': 'report available', 'other': 'reports available'}"></ng-pluralize>
</div>

</td>
<td>
<a href ng-click="addFilterValue('startDate', artifact.startDate)"><span uib-tooltip="{{artifact.startDate | showDate}}" tooltip-popup-delay="500" tooltip-placement="bottom">{{artifact.startDate | shortDate}}</span></a>
Expand Down
2 changes: 1 addition & 1 deletion ui/bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "thehive",
"version": "2.11.1",
"version": "2.11.2",
"license": "AGPL-3.0",
"dependencies": {
"angular": "1.5.8",
Expand Down
2 changes: 1 addition & 1 deletion ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "thehive",
"version": "2.11.1",
"version": "2.11.2",
"license": "AGPL-3.0",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion version.sbt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version in ThisBuild := "2.11.1"
version in ThisBuild := "2.11.2"

0 comments on commit f7b0ce8

Please sign in to comment.