mirror of https://github.com/MISP/MISP
new: add basic experimental support for PostgreSQL
parent
9656913bd1
commit
9bf0e16ac6
|
@ -61,10 +61,12 @@ class DATABASE_CONFIG {
|
|||
|
||||
public $default = array(
|
||||
'datasource' => 'Database/Mysql',
|
||||
//'datasource' => 'Database/Postgres',
|
||||
'persistent' => false,
|
||||
'host' => 'localhost',
|
||||
'login' => 'db login',
|
||||
'port' => 3306,
|
||||
'port' => 3306, // MySQL & MariaDB
|
||||
//'port' => 5432, // PostgreSQL
|
||||
'password' => 'db password',
|
||||
'database' => 'misp',
|
||||
'prefix' => '',
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<?php
|
||||
class UserInitShell extends AppShell {
|
||||
public $uses = array('User', 'Role', 'Organisation', 'Server');
|
||||
public $uses = array('User', 'Role', 'Organisation', 'Server', 'ConnectionManager');
|
||||
public function main() {
|
||||
if (!Configure::read('Security.salt')) {
|
||||
$this->loadModel('Server');
|
||||
$this->Server->serverSettingsSaveValue('Security.salt', $this->User->generateRandomPassword(32));
|
||||
}
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
$this->Role->Behaviors->unload('SysLogLogable.SysLogLogable');
|
||||
$this->User->Behaviors->unload('SysLogLogable.SysLogLogable');
|
||||
// populate the DB with the first role (site admin) if it's empty
|
||||
|
@ -29,6 +31,11 @@ class UserInitShell extends AppShell {
|
|||
'perm_template' => 1
|
||||
));
|
||||
$this->Role->save($siteAdmin);
|
||||
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "SELECT setval('roles_id_seq', (SELECT MAX(id) FROM roles));";
|
||||
$this->Role->query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
|
||||
|
@ -41,6 +48,11 @@ class UserInitShell extends AppShell {
|
|||
'local' => 1
|
||||
));
|
||||
$this->Organisation->save($org);
|
||||
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "SELECT setval('organisations_id_seq', (SELECT MAX(id) FROM organisations));";
|
||||
$this->Organisation->query($sql);
|
||||
}
|
||||
$org_id = $this->Organisation->id;
|
||||
} else {
|
||||
$hostOrg = $this->Organisation->find('first', array('conditions' => array('Organisation.name' => Configure::read('MISP.org')), 'recursive' => -1));
|
||||
|
@ -69,6 +81,11 @@ class UserInitShell extends AppShell {
|
|||
));
|
||||
$this->User->validator()->remove('password'); // password is to simple, remove validation
|
||||
$this->User->save($admin);
|
||||
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));";
|
||||
$this->User->query($sql);
|
||||
}
|
||||
echo $authkey . PHP_EOL;
|
||||
} else {
|
||||
echo 'Script aborted: MISP instance already initialised.' . PHP_EOL;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
// TODO GPG encryption has issues when keys are expired
|
||||
|
||||
App::uses('ConnectionManager', 'Model');
|
||||
App::uses('Controller', 'Controller');
|
||||
App::uses('File', 'Utility');
|
||||
App::uses('RequestRearrangeTool', 'Tools');
|
||||
|
@ -79,6 +80,13 @@ class AppController extends Controller {
|
|||
);
|
||||
|
||||
public function beforeFilter() {
|
||||
// check for a supported datasource configuration
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
if ($dataSource != 'Database/Mysql' && $dataSource != 'Database/Postgres') {
|
||||
throw new Exception('datasource not supported: ' . $dataSource);
|
||||
}
|
||||
|
||||
$this->set('jsVersion', $this->__jsVersion);
|
||||
$this->loadModel('User');
|
||||
$auth_user_fields = $this->User->describeAuthFields();
|
||||
|
|
|
@ -556,6 +556,8 @@ class UsersController extends AppController {
|
|||
// $this->redirect($this->Auth->redirectUrl());
|
||||
$this->redirect(array('controller' => 'events', 'action' => 'index'));
|
||||
} else {
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
// don't display authError before first login attempt
|
||||
if (str_replace("//","/",$this->webroot . $this->Session->read('Auth.redirect')) == $this->webroot && $this->Session->read('Message.auth.message') == $this->Auth->authError) {
|
||||
$this->Session->delete('Message.auth');
|
||||
|
@ -586,6 +588,11 @@ class UsersController extends AppController {
|
|||
'perm_tagger' => 1,
|
||||
));
|
||||
$this->Role->save($siteAdmin);
|
||||
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "SELECT setval('roles_id_seq', (SELECT MAX(id) FROM roles));";
|
||||
$this->Role->query($sql);
|
||||
}
|
||||
}
|
||||
if ($this->User->Organisation->find('count', array('conditions' => array('Organisation.local' => true))) == 0) {
|
||||
$org = array('Organisation' => array(
|
||||
|
@ -599,6 +606,11 @@ class UsersController extends AppController {
|
|||
'nationality' => ''
|
||||
));
|
||||
$this->User->Organisation->save($org);
|
||||
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "SELECT setval('organisations_id_seq', (SELECT MAX(id) FROM organisations));";
|
||||
$this->User->Organisation->query($sql);
|
||||
}
|
||||
$org_id = $this->User->Organisation->id;
|
||||
} else {
|
||||
$hostOrg = $this->User->Organisation->find('first', array('conditions' => array('Organisation.name' => Configure::read('MISP.org'), 'Organisation.local' => true), 'recursive' => -1));
|
||||
|
@ -625,6 +637,11 @@ class UsersController extends AppController {
|
|||
));
|
||||
$this->User->validator()->remove('password'); // password is too simple, remove validation
|
||||
$this->User->save($admin);
|
||||
// PostgreSQL: update value of auto incremented serial primary key after setting the column by force
|
||||
if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "SELECT setval('users_id_seq', (SELECT MAX(id) FROM users));";
|
||||
$this->User->query($sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -693,6 +710,7 @@ class UsersController extends AppController {
|
|||
));
|
||||
$orgs = array();
|
||||
foreach ($temp as $t) {
|
||||
if (!isset($t['Event'])) $t['Event'] = $t[0]; // Postgres workaround, array element has index 0 instead of Event
|
||||
$orgs[$t['Event']['orgc_id']] = $t['Orgc']['name'];
|
||||
}
|
||||
// What org posted what type of attribute
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('ConnectionManager', 'Model');
|
||||
App::uses('Sanitize', 'Utility');
|
||||
|
||||
class Bruteforce extends AppModel {
|
||||
|
||||
public function insert($ip, $username) {
|
||||
$expire = time() + Configure::read('SecureAuth.expire');
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
// sanitize fields
|
||||
$ip = Sanitize::clean($ip);
|
||||
$username = Sanitize::clean($username);
|
||||
$this->query("INSERT INTO bruteforces (ip, username, `expire`) VALUES ('$ip', '$username', '$expire');");
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = "INSERT INTO bruteforces (ip, username, `expire`) VALUES ('$ip', '$username', '$expire');";
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sql = "INSERT INTO bruteforces (ip, username, expire) VALUES ('$ip', '$username', '$expire');";
|
||||
}
|
||||
$this->query($sql);
|
||||
if ($this->isBlacklisted($ip, $username)) {
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$this->Log->create();
|
||||
|
@ -25,7 +33,14 @@ class Bruteforce extends AppModel {
|
|||
}
|
||||
|
||||
public function clean() {
|
||||
$this->query("DELETE FROM bruteforces WHERE `expire` <= NOW();");
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'DELETE FROM bruteforces WHERE `expire` <= NOW();';
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'DELETE FROM bruteforces WHERE expire <= NOW();';
|
||||
}
|
||||
$this->query($sql);
|
||||
}
|
||||
|
||||
public function isBlacklisted($ip,$username) {
|
||||
|
|
|
@ -82,6 +82,8 @@ class Log extends AppModel {
|
|||
}
|
||||
|
||||
public function returnDates($org = 'all') {
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
$conditions = array();
|
||||
$this->Organisation = ClassRegistry::init('Organisation');
|
||||
if ($org !== 'all') {
|
||||
|
@ -90,12 +92,27 @@ class Log extends AppModel {
|
|||
$conditions['org'] = $org['Organisation']['name'];
|
||||
}
|
||||
$conditions['AND']['NOT'] = array('action' => array('login', 'logout', 'changepw'));
|
||||
$validDates = $this->find('all', array(
|
||||
'fields' => array('DISTINCT UNIX_TIMESTAMP(DATE(created)) AS Date', 'count(id) AS count'),
|
||||
'conditions' => $conditions,
|
||||
'group' => array('Date'),
|
||||
'order' => array('Date')
|
||||
));
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$validDates = $this->find('all', array(
|
||||
'fields' => array('DISTINCT UNIX_TIMESTAMP(DATE(created)) AS Date', 'count(id) AS count'),
|
||||
'conditions' => $conditions,
|
||||
'group' => array('Date'),
|
||||
'order' => array('Date')
|
||||
));
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
// manually generate the query for Postgres
|
||||
// cakephp ORM would escape "DATE" datatype in CAST expression
|
||||
$condnotinaction = "'" . implode("', '", $conditions['AND']['NOT']['action']) . "'";
|
||||
if (!empty($conditions['org'])) $condOrg = ' AND org = "' . $conditions['org'] . '"';
|
||||
else $condOrg = '';
|
||||
$sql = 'SELECT DISTINCT EXTRACT(EPOCH FROM CAST(created AS DATE)) AS "Date",
|
||||
COUNT(id) AS count
|
||||
FROM logs
|
||||
WHERE action NOT IN (' . $condnotinaction . ')
|
||||
' . $condOrg . '
|
||||
GROUP BY "Date" ORDER BY "Date"';
|
||||
$validDates = $this->query($sql);
|
||||
}
|
||||
$data = array();
|
||||
foreach ($validDates as $k => $date) {
|
||||
$data[$date[0]['Date']] = intval($date[0]['count']);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
App::uses('AppModel', 'Model');
|
||||
App::uses('ConnectionManager', 'Model');
|
||||
class Organisation extends AppModel{
|
||||
|
||||
public $useTable = 'organisations';
|
||||
|
@ -192,13 +193,20 @@ class Organisation extends AppModel{
|
|||
if (empty($currentOrg) || empty($targetOrg)) throw new MethodNotAllowedException('Something went wrong with the organisation merge. Organisation not found.');
|
||||
$dir = new Folder();
|
||||
$this->Log = ClassRegistry::init('Log');
|
||||
$dataSourceConfig = ConnectionManager::getDataSource('default')->config;
|
||||
$dataSource = $dataSourceConfig['datasource'];
|
||||
$dirPath = APP . 'tmp' . DS . 'logs' . DS . 'merges';
|
||||
if (!$dir->create($dirPath)) throw new MethodNotAllowedException('Merge halted because the log directory (default: /var/www/MISP/app/tmp/logs/merges) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
|
||||
$logFile = new File($dirPath . DS . 'merge_' . $currentOrg['Organisation']['id'] . '_' . $targetOrg['Organisation']['id'] . '_' . time() . '.log');
|
||||
if (!$logFile->create()) throw new MethodNotAllowedException('Merge halted because the log file (default location: /var/www/MISP/app/tmp/logs/merges/[old_org_id]_[new_org_id]_timestamp.log) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
|
||||
$backupFile = new File($dirPath . DS . 'merge_' . $currentOrg['Organisation']['id'] . '_' . $targetOrg['Organisation']['id'] . '_' . time() . '.sql');
|
||||
if (!$backupFile->create()) throw new MethodNotAllowedException('Merge halted because the backup script file (default location: /var/www/MISP/app/tmp/logs/merges/[old_org_id]_[new_org_id]_timestamp.sql) could not be created. This is most likely a permission issue, make sure that MISP can write to the logs directory and try again.');
|
||||
$backupFile->append('INSERT INTO organisations (`' . implode('`, `', array_keys($currentOrg['Organisation'])) . '`) VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');' . PHP_EOL);
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'INSERT INTO organisations (`' . implode('`, `', array_keys($currentOrg['Organisation'])) . '`) VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');';
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'INSERT INTO organisations ("' . implode('", "', array_keys($currentOrg['Organisation'])) . '") VALUES (\'' . implode('\', \'', array_values($currentOrg['Organisation'])) . '\');';
|
||||
}
|
||||
$backupFile->append($sql . PHP_EOL);
|
||||
$this->Log->create();
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
|
@ -214,14 +222,29 @@ class Organisation extends AppModel{
|
|||
$success = true;
|
||||
foreach ($this->organisationAssociations as $model => $data) {
|
||||
foreach ($data['fields'] as $field) {
|
||||
$temp = $this->query('SELECT `id` FROM `' . $data['table'] . '` WHERE `' . $field . '` = "' . $currentOrg['Organisation']['id'] . '"');
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'SELECT `id` FROM `' . $data['table'] . '` WHERE `' . $field . '` = "' . $currentOrg['Organisation']['id'] . '"';
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'SELECT "id" FROM "' . $data['table'] . '" WHERE "' . $field . '" = "' . $currentOrg['Organisation']['id'] . '"';
|
||||
}
|
||||
$temp = $this->query($sql);
|
||||
if (!empty($temp)) {
|
||||
$dataMoved['values_changed'][$model][$field] = Set::extract('/' . $data['table'] . '/id', $temp);
|
||||
if (!empty($dataMoved['values_changed'][$model][$field])) {
|
||||
$this->Log->create();
|
||||
try {
|
||||
$result = $this->query('UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $targetOrg['Organisation']['id'] . ' WHERE `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ';');
|
||||
$backupFile->append('UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ' WHERE `id` IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');' . PHP_EOL);
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $targetOrg['Organisation']['id'] . ' WHERE `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ';';
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $targetOrg['Organisation']['id'] . ' WHERE "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ';';
|
||||
}
|
||||
$result = $this->query($sql);
|
||||
if ($dataSource == 'Database/Mysql') {
|
||||
$sql = 'UPDATE `' . $data['table'] . '` SET `' . $field . '` = ' . $currentOrg['Organisation']['id'] . ' WHERE `id` IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
|
||||
} else if ($dataSource == 'Database/Postgres') {
|
||||
$sql = 'UPDATE "' . $data['table'] . '" SET "' . $field . '" = ' . $currentOrg['Organisation']['id'] . ' WHERE "id" IN (' . implode(',', $dataMoved['values_changed'][$model][$field]) . ');';
|
||||
}
|
||||
$backupFile->append($sql . PHP_EOL);
|
||||
$this->Log->save(array(
|
||||
'org' => $user['Organisation']['name'],
|
||||
'model' => 'Organisation',
|
||||
|
|
Loading…
Reference in New Issue