mirror of https://github.com/MISP/MISP
new: [cerebrate:pull_sg] Pull sharing groups from a cerebrate instance
parent
8665076156
commit
bcf801e1bd
|
@ -115,7 +115,7 @@ class CerebratesController extends AppController
|
|||
$result = $this->Cerebrate->saveRemoteOrgs($result);
|
||||
$message = __('Added %s new organisations, updated %s existing organisations, %s failures.', $result['add'], $result['edit'], $result['fails']);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Cerebrates', 'pull_orgs', $cerebrate_id . '/' . $org_id, false, $message);
|
||||
return $this->RestResponse->saveSuccessResponse('Cerebrates', 'pull_orgs', $cerebrate_id, false, $message);
|
||||
} else {
|
||||
$this->Flash->success($message);
|
||||
$this->redirect($this->referer());
|
||||
|
@ -128,10 +128,46 @@ class CerebratesController extends AppController
|
|||
$this->layout = 'ajax';
|
||||
$this->render('/genericTemplates/confirm');
|
||||
}
|
||||
}
|
||||
|
||||
public function pull_sgs($id)
|
||||
{
|
||||
$this->set('menuData', ['menuList' => 'sync', 'menuItem' => 'previewCerebrateSgs']);
|
||||
$cerebrate = $this->Cerebrate->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => ['Cerebrate.id' => $id]
|
||||
]);
|
||||
if (empty($cerebrate)) {
|
||||
throw new NotFoundException(__('Invalid Cerebrate instance ID provided.'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
$result = $this->Cerebrate->queryInstance([
|
||||
'cerebrate' => $cerebrate,
|
||||
'path' => '/sharingGroups/index',
|
||||
'params' => $this->IndexFilter->harvestParameters([
|
||||
'name',
|
||||
'uuid',
|
||||
'quickFilter'
|
||||
]),
|
||||
'type' => 'GET'
|
||||
]);
|
||||
$result = $this->Cerebrate->saveRemoteSgs($result, $this->Auth->user());
|
||||
$message = __('Added %s new sharing groups, updated %s existing sharing groups, %s failures.', $result['add'], $result['edit'], $result['fails']);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->saveSuccessResponse('Cerebrates', 'pull_sgs', $cerebrate_id, false, $message);
|
||||
} else {
|
||||
$this->Flash->success($message);
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
} else {
|
||||
$this->set('id', $cerebrate['Cerebrate']['id']);
|
||||
$this->set('title', __('Sync sharing group information'));
|
||||
$this->set('question', __('Are you sure you want to download and add / update the remote sharing group from the Cerebrate node?'));
|
||||
$this->set('actionName', __('Pull all'));
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/genericTemplates/confirm');
|
||||
}
|
||||
}
|
||||
|
||||
public function preview_orgs($id)
|
||||
|
@ -186,7 +222,7 @@ class CerebratesController extends AppController
|
|||
if (is_array($saveResult)) {
|
||||
return $this->RestResponse->viewData($saveResult, $this->response->type());
|
||||
} else {
|
||||
return $this->RestResponse->saveFailResponse('Cerebrates', 'download_org', $cerebrate_id . '/' . $org_id, $aveResult);
|
||||
return $this->RestResponse->saveFailResponse('Cerebrates', 'download_org', $cerebrate_id . '/' . $org_id, $saveResult);
|
||||
}
|
||||
} else {
|
||||
if (is_array($saveResult)) {
|
||||
|
@ -205,4 +241,76 @@ class CerebratesController extends AppController
|
|||
$this->render('/genericTemplates/confirm');
|
||||
}
|
||||
}
|
||||
|
||||
public function preview_sharing_groups($id)
|
||||
{
|
||||
$this->set('menuData', ['menuList' => 'sync', 'menuItem' => 'previewCerebrateSGs']);
|
||||
$cerebrate = $this->Cerebrate->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => ['Cerebrate.id' => $id]
|
||||
]);
|
||||
if (empty($cerebrate)) {
|
||||
throw new NotFoundException(__('Invalid Cerebrate instance ID provided.'));
|
||||
}
|
||||
$result = $this->Cerebrate->queryInstance([
|
||||
'cerebrate' => $cerebrate,
|
||||
'path' => '/sharingGroups/index',
|
||||
'params' => $this->IndexFilter->harvestParameters([
|
||||
'name',
|
||||
'uuid',
|
||||
'quickFilter'
|
||||
]),
|
||||
'type' => 'GET'
|
||||
]);
|
||||
$result = $this->Cerebrate->checkRemoteSharingGroups($result);
|
||||
if ($this->_isRest()) {
|
||||
return $this->RestResponse->viewData($result, $this->response->type());
|
||||
} else {
|
||||
App::uses('CustomPaginationTool', 'Tools');
|
||||
$customPagination = new CustomPaginationTool();
|
||||
$customPagination->truncateAndPaginate($result, $this->params, false, true);
|
||||
$this->set('data', $result);
|
||||
$this->set('cerebrate', $cerebrate);
|
||||
}
|
||||
}
|
||||
|
||||
public function download_sg($cerebrate_id, $sg_id)
|
||||
{
|
||||
if ($this->request->is('post')) {
|
||||
$cerebrate = $this->Cerebrate->find('first', [
|
||||
'recursive' => -1,
|
||||
'conditions' => ['Cerebrate.id' => $cerebrate_id]
|
||||
]);
|
||||
if (empty($cerebrate)) {
|
||||
throw new NotFoundException(__('Invalid Cerebrate instance ID provided.'));
|
||||
}
|
||||
$result = $this->Cerebrate->queryInstance([
|
||||
'cerebrate' => $cerebrate,
|
||||
'path' => '/sharingGroups/view/' . $sg_id,
|
||||
'type' => 'GET'
|
||||
]);
|
||||
$saveResult = $this->Cerebrate->captureSg($result, $this->Auth->user());
|
||||
if ($this->_isRest()) {
|
||||
if (is_array($saveResult)) {
|
||||
return $this->RestResponse->viewData($saveResult, $this->response->type());
|
||||
} else {
|
||||
return $this->RestResponse->saveFailResponse('Cerebrates', 'download_sg', $cerebrate_id . '/' . $sg_id, $saveResult);
|
||||
}
|
||||
} else {
|
||||
if (is_array($saveResult)) {
|
||||
$this->Flash->success(__('Sharing Group downloaded.'));
|
||||
} else {
|
||||
$this->Flash->error($saveResult);
|
||||
}
|
||||
$this->redirect($this->referer());
|
||||
}
|
||||
} else {
|
||||
$this->set('id', $cerebrate_id);
|
||||
$this->set('title', __('Download sharing group information'));
|
||||
$this->set('question', __('Are you sure you want to download and add / update the remote sharing group?'));
|
||||
$this->set('actionName', __('Download'));
|
||||
$this->layout = 'ajax';
|
||||
$this->render('/genericTemplates/confirm');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,6 +109,32 @@ class Cerebrate extends AppModel
|
|||
return $outcome;
|
||||
}
|
||||
|
||||
public function saveRemoteSgs($sgs, $user)
|
||||
{
|
||||
$outcome = [
|
||||
'add' => 0,
|
||||
'edit' => 0,
|
||||
'fails' => 0
|
||||
];
|
||||
foreach ($sgs as $sg) {
|
||||
$isEdit = false;
|
||||
$noChange = false;
|
||||
$result = $this->captureSg($sg, $user, $isEdit, $noChange);
|
||||
if (!is_array($result)) {
|
||||
$outcome['fails'] += 1;
|
||||
} else {
|
||||
if ($isEdit) {
|
||||
if (!$noChange) {
|
||||
$outcome['edit'] += 1;
|
||||
}
|
||||
} else {
|
||||
$outcome['add'] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $outcome;
|
||||
}
|
||||
|
||||
public function captureOrg($org_data, &$edit=false, &$noChange=false) {
|
||||
$org = $this->convertOrg($org_data);
|
||||
if ($org) {
|
||||
|
@ -226,6 +252,165 @@ class Cerebrate extends AppModel
|
|||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
private function __compareMembers($existingMembers, $remoteMembers)
|
||||
{
|
||||
$memberFound = [];
|
||||
$memberNotFound = [];
|
||||
foreach ($remoteMembers as $remoteMember) {
|
||||
$found = false;
|
||||
foreach ($existingMembers as $existingMember) {
|
||||
if ($existingMember['uuid'] == $remoteMember['uuid']) {
|
||||
$found = true;
|
||||
$memberFound[] = $remoteMember['uuid'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
$memberNotFound[] = $remoteMember['uuid'];
|
||||
}
|
||||
}
|
||||
return empty($memberNotFound);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks remote for the current status of each sharing groups
|
||||
* Adds the exists_locally field with a boolean status
|
||||
* If exists_loally is true, adds a list with the differences (keynames)
|
||||
*/
|
||||
public function checkRemoteSharingGroups($sgs)
|
||||
{
|
||||
$this->SharingGroup = ClassRegistry::init('SharingGroup');
|
||||
$uuids = Hash::extract($sgs, '{n}.uuid');
|
||||
$existingSgs = $this->SharingGroup->find('all', [
|
||||
'recursive' => -1,
|
||||
'contain' => [
|
||||
'SharingGroupOrg' => ['Organisation'],
|
||||
'Organisation',
|
||||
],
|
||||
'conditions' => [
|
||||
'SharingGroup.uuid' => $uuids
|
||||
],
|
||||
]);
|
||||
$rearranged = [];
|
||||
foreach ($existingSgs as $existingSg) {
|
||||
$existingSg['SharingGroup']['SharingGroupOrg'] = $existingSg['SharingGroupOrg'];
|
||||
$existingSg['SharingGroup']['Organisation'] = $existingSg['Organisation'];
|
||||
$rearranged[$existingSg['SharingGroup']['uuid']] = $existingSg['SharingGroup'];
|
||||
}
|
||||
unset($existingSgs);
|
||||
$fieldsToCheck = ['name', 'releasability', 'description'];
|
||||
foreach ($sgs as $k => $sg) {
|
||||
$sgs[$k]['exists_locally'] = false;
|
||||
if (isset($rearranged[$sg['uuid']])) {
|
||||
$sgs[$k]['exists_locally'] = true;
|
||||
$sgs[$k]['differences'] = $this->compareSgs($rearranged[$sg['uuid']], $sgs[$k]);
|
||||
}
|
||||
}
|
||||
return $sgs;
|
||||
}
|
||||
|
||||
private function compareSgs($existingSg, $remoteSg)
|
||||
{
|
||||
$differences = [];
|
||||
$fieldsToCheck = ['name', 'releasability', 'description'];
|
||||
|
||||
foreach ($fieldsToCheck as $fieldToCheck) {
|
||||
if (
|
||||
!(empty($remoteSg[$fieldToCheck]) && empty($existingSg[$fieldToCheck])) &&
|
||||
$remoteSg[$fieldToCheck] !== $existingSg[$fieldToCheck]
|
||||
) {
|
||||
if ($fieldToCheck === 'name') {
|
||||
if ($this->__compareNames($existingSg[$fieldToCheck], $remoteSg[$fieldToCheck])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$differences[] = $fieldToCheck;
|
||||
}
|
||||
}
|
||||
if (!$this->__compareMembers(Hash::extract($existingSg['SharingGroupOrg'], '{n}.Organisation'), $remoteSg['sharing_group_orgs'])) {
|
||||
$differences[] = 'members';
|
||||
}
|
||||
return $differences;
|
||||
}
|
||||
|
||||
private function convertSg($sg_data)
|
||||
{
|
||||
$mapping = [
|
||||
'name' => [
|
||||
'field' => 'name',
|
||||
'required' => 1
|
||||
],
|
||||
'uuid' => [
|
||||
'field' => 'uuid',
|
||||
'required' => 1
|
||||
],
|
||||
'releasability' => [
|
||||
'field' => 'releasability'
|
||||
],
|
||||
'description' => [
|
||||
'field' => 'description'
|
||||
],
|
||||
];
|
||||
$sg = [];
|
||||
foreach ($mapping as $cerebrate_field => $field_data) {
|
||||
if (empty($sg_data[$cerebrate_field])) {
|
||||
if (!empty($field_data['required'])) {
|
||||
return false;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$sg[$field_data['field']] = $sg_data[$cerebrate_field];
|
||||
}
|
||||
$sg['SharingGroupOrg'] = [];
|
||||
if (!empty($sg_data['sharing_group_orgs'])) {
|
||||
$sg['SharingGroupOrg'] = $sg_data['sharing_group_orgs'];
|
||||
foreach ($sg['SharingGroupOrg'] as $k => $org) {
|
||||
if (isset($org['_joinData'])) {
|
||||
unset($sg['SharingGroupOrg'][$k]['_joinData']);
|
||||
}
|
||||
if (!isset($org['extend'])) {
|
||||
$sg['SharingGroupOrg'][$k]['extend'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $sg;
|
||||
}
|
||||
|
||||
public function captureSg($sg_data, $user, &$edit=false, &$noChange=false) {
|
||||
$this->SharingGroup = ClassRegistry::init('SharingGroup');
|
||||
$sg = $this->convertSg($sg_data);
|
||||
if ($sg) {
|
||||
$existingSg = $this->SharingGroup->find('first', [
|
||||
'recursive' => -1,
|
||||
'contain' => [
|
||||
'SharingGroupOrg' => ['Organisation'],
|
||||
'Organisation',
|
||||
],
|
||||
'conditions' => [
|
||||
'SharingGroup.uuid' => $sg_data['uuid']
|
||||
],
|
||||
]);
|
||||
if (!empty($existingSg)) {
|
||||
$edit = true;
|
||||
}
|
||||
$captureResult = $this->SharingGroup->captureSG($sg, $user, false);
|
||||
if (!empty($captureResult)) {
|
||||
$savedSg = $this->SharingGroup->find('first', [
|
||||
'recursive' => -1,
|
||||
'contain' => [
|
||||
'SharingGroupOrg' => ['Organisation'],
|
||||
'Organisation',
|
||||
],
|
||||
'conditions' => [
|
||||
'SharingGroup.id' => $captureResult
|
||||
],
|
||||
]);
|
||||
return $savedSg;
|
||||
}
|
||||
return __('The organisation could not be saved.');
|
||||
}
|
||||
return __('The retrieved data isn\'t a valid sharing group.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,15 @@
|
|||
'title' => __('Pull all organisations'),
|
||||
'icon' => 'arrow-circle-down'
|
||||
],
|
||||
[
|
||||
'onclick' => sprintf(
|
||||
'openGenericModal(\'%s/cerebrates/pull_sgs/[onclick_params_data_path]\');',
|
||||
$baseurl
|
||||
),
|
||||
'onclick_params_data_path' => 'Cerebrate.id',
|
||||
'title' => __('Pull all sharing groups'),
|
||||
'icon' => 'arrow-circle-down'
|
||||
],
|
||||
[
|
||||
'url' => $baseurl . '/cerebrates/edit',
|
||||
'url_params_data_paths' => ['Cerebrate.id'],
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
$fields = [
|
||||
[
|
||||
'name' => __('Id'),
|
||||
'sort' => 'id',
|
||||
'data_path' => 'id'
|
||||
],
|
||||
[
|
||||
'name' => __('Status'),
|
||||
'sort' => 'exists_locally',
|
||||
'element' => 'remote_status',
|
||||
'data_path' => ''
|
||||
],
|
||||
[
|
||||
'name' => __('UUID'),
|
||||
'sort' => 'uuid',
|
||||
'data_path' => 'uuid'
|
||||
],
|
||||
[
|
||||
'name' => __('Name'),
|
||||
'sort' => 'name',
|
||||
'data_path' => 'name'
|
||||
],
|
||||
[
|
||||
'name' => __('Releasability'),
|
||||
'sort' => 'releasability',
|
||||
'data_path' => 'releasability'
|
||||
],
|
||||
[
|
||||
'name' => __('Description'),
|
||||
'sort' => 'description',
|
||||
'data_path' => 'description'
|
||||
],
|
||||
[
|
||||
'name' => __('# Member'),
|
||||
'element' => 'custom',
|
||||
'function' => function($row) {
|
||||
return count($row['sharing_group_orgs']);
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
echo $this->element('genericElements/IndexTable/scaffold', [
|
||||
'scaffold_data' => [
|
||||
'data' => [
|
||||
'data' => $data,
|
||||
'top_bar' => [
|
||||
'pull' => 'right',
|
||||
'children' => [
|
||||
[
|
||||
'type' => 'search',
|
||||
'button' => __('Filter'),
|
||||
'placeholder' => __('Enter value to search'),
|
||||
'data' => '',
|
||||
'preserve_url_params' => [$cerebrate['Cerebrate']['id']],
|
||||
'searchKey' => 'quickFilter'
|
||||
]
|
||||
]
|
||||
],
|
||||
'fields' => $fields,
|
||||
'title' => empty($ajax) ? __(
|
||||
'Sharing group list via Cerebrate %s (%s)',
|
||||
h($cerebrate['Cerebrate']['id']),
|
||||
h($cerebrate['Cerebrate']['name'])
|
||||
) : false,
|
||||
'description' => empty($ajax) ? __('Preview of the sharing group known to the remote Cerebrate instance.') : false,
|
||||
'actions' => [
|
||||
[
|
||||
'onclick' => sprintf(
|
||||
'openGenericModal(\'%s/cerebrates/download_sg/%s/[onclick_params_data_path]\');',
|
||||
$baseurl,
|
||||
h($cerebrate['Cerebrate']['id'])
|
||||
),
|
||||
'onclick_params_data_path' => 'id',
|
||||
'icon' => 'download',
|
||||
'title' => __('Fetch sharing group object')
|
||||
]
|
||||
],
|
||||
'paginatorOptions' => [
|
||||
'url' => [$cerebrate['Cerebrate']['id']]
|
||||
],
|
||||
'persistUrlParams' => [0, 'quickFilter']
|
||||
],
|
||||
'containerId' => 'preview_sgs_container'
|
||||
]
|
||||
]);
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
var passedArgsArray = <?= json_encode([h($cerebrate['Cerebrate']['id'])]) ?>;
|
||||
</script>
|
|
@ -56,7 +56,13 @@ echo $this->element(
|
|||
'url_params' => ['Cerebrate.id'],
|
||||
'title' => __('Organisations'),
|
||||
'elementId' => 'preview_orgs_container'
|
||||
]
|
||||
],
|
||||
[
|
||||
'url' => '/cerebrates/preview_sharing_groups/{{0}}/',
|
||||
'url_params' => ['Cerebrate.id'],
|
||||
'title' => __('Sharing Groups'),
|
||||
'elementId' => 'preview_sgs_container'
|
||||
],
|
||||
]
|
||||
]
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue