Merge branch 'develop' of github.com:cerebrate-project/cerebrate into develop
commit
6b53d6d81a
|
@ -2,7 +2,7 @@ name: test
|
|||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
branches: [main, develop, fix-test-action]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
|
||||
|
@ -14,9 +14,9 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
php: ["7.4"]
|
||||
php: ["8.2"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Create config files
|
||||
run: |
|
||||
|
|
|
@ -178,7 +178,6 @@ return [
|
|||
*/
|
||||
'Error' => [
|
||||
'errorLevel' => E_ALL,
|
||||
'exceptionRenderer' => ExceptionRenderer::class,
|
||||
'skipLog' => [],
|
||||
'log' => true,
|
||||
'trace' => true,
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
<testsuite name="api">
|
||||
<directory>./tests/TestCase/Api</directory>
|
||||
</testsuite>
|
||||
<testsuite name="e2e">
|
||||
<directory>./tests/TestCase/Integration</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<extensions>
|
||||
|
|
|
@ -106,7 +106,7 @@ class TagHelper extends Helper
|
|||
$deleteButton = $this->Bootstrap->button([
|
||||
'size' => 'sm',
|
||||
'icon' => 'times',
|
||||
'class' => ['ms-1', 'border-0', "text-${textColour}"],
|
||||
'class' => ['ms-1', 'border-0', "text-$textColour"],
|
||||
'variant' => 'text',
|
||||
'title' => __('Delete tag'),
|
||||
'onclick' => sprintf('deleteTag(\'%s\', \'%s\', this)',
|
||||
|
|
|
@ -136,7 +136,7 @@ class ImporterCommand extends Command
|
|||
$entity = null;
|
||||
if (isset($item[$primary_key])) {
|
||||
$query = $table->find('all')
|
||||
->where(["${primary_key}" => $item[$primary_key]]);
|
||||
->where(["$primary_key" => $item[$primary_key]]);
|
||||
$entity = $query->first();
|
||||
}
|
||||
if (is_null($entity)) {
|
||||
|
|
|
@ -102,7 +102,7 @@ class CRUDComponent extends Component
|
|||
|
||||
if (!$this->Controller->ParamHandler->isRest()) {
|
||||
$this->setRequestedEntryAmount();
|
||||
} else if (!empty($this->request->getQuery('limit'))) {
|
||||
} else if (empty($this->request->getQuery('limit'))) {
|
||||
$this->Controller->paginate['limit'] = PHP_INT_MAX; // Make sure to download the entire filtered table
|
||||
}
|
||||
$data = $this->Controller->paginate($query, $this->Controller->paginate ?? []);
|
||||
|
@ -1489,7 +1489,7 @@ class CRUDComponent extends Component
|
|||
{
|
||||
$prefixedConditions = [];
|
||||
foreach ($conditions as $condField => $condValue) {
|
||||
$prefixedConditions["${prefix}.${condField}"] = $condValue;
|
||||
$prefixedConditions["$prefix.$condField"] = $condValue;
|
||||
}
|
||||
return $prefixedConditions;
|
||||
}
|
||||
|
@ -1613,13 +1613,13 @@ class CRUDComponent extends Component
|
|||
[sprintf('%s.id = %s.%s', $this->Table->getAlias(), $associatedTable->getAlias(), $association->getForeignKey())]
|
||||
)
|
||||
->where([
|
||||
["${field} IS NOT" => NULL]
|
||||
["$field IS NOT" => NULL]
|
||||
]);
|
||||
} else if ($associationType == 'manyToOne') {
|
||||
$fieldToExtract = sprintf('%s.%s', Inflector::singularize(strtolower($model)), $subField);
|
||||
$query = $this->Table->find()->contain($model);
|
||||
} else {
|
||||
throw new Exception("Association ${associationType} not supported in CRUD Component");
|
||||
throw new Exception("Association $associationType not supported in CRUD Component");
|
||||
}
|
||||
} else {
|
||||
$fieldToExtract = $field;
|
||||
|
|
|
@ -390,7 +390,7 @@ class RestResponseComponent extends Component
|
|||
return '[]';
|
||||
}
|
||||
|
||||
public function saveFailResponse($controller, $action, $id = false, $validationErrors, $format = false)
|
||||
public function saveFailResponse($controller, $action, $id, $validationErrors, $format = false)
|
||||
{
|
||||
$this->autoRender = false;
|
||||
$response = array();
|
||||
|
|
|
@ -61,6 +61,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('Broods Index'),
|
||||
'description' => __('Cerebrate can connect to other Cerebrate instances to exchange trust information and to instrument interconnectivity between connected local tools. Each such Cerebrate instance with its connected tools is considered to be a brood.'),
|
||||
'includeAllPagination' => true,
|
||||
'pull' => 'right',
|
||||
'actions' => [
|
||||
[
|
||||
|
|
|
@ -78,6 +78,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('ContactDB Individuals Index'),
|
||||
'description' => __('A list of individuals known by your Cerebrate instance. This list can get populated either directly, by adding new individuals or by fetching them from trusted remote sources. Additionally, users created for the platform will always have an individual identity.'),
|
||||
'includeAllPagination' => true,
|
||||
'actions' => [
|
||||
[
|
||||
'url' => '/individuals/view',
|
||||
|
|
|
@ -169,6 +169,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('Meta Field Templates'),
|
||||
'description' => __('The various templates used to enrich certain objects by a set of standardised fields.'),
|
||||
'includeAllPagination' => true,
|
||||
'actions' => [
|
||||
[
|
||||
'url' => '/metaTemplates/view',
|
||||
|
|
|
@ -62,6 +62,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('Organisation Groups Index'),
|
||||
'description' => __('OrgGroups are an administrative concept, multiple organisations can belong to a grouping that allows common management by so called "GroupAdmins". This helps grouping organisations by sector, country or other commonalities into co-managed sub-communities.'),
|
||||
'includeAllPagination' => true,
|
||||
'actions' => [
|
||||
[
|
||||
'url' => '/orgGroups/view',
|
||||
|
|
|
@ -97,6 +97,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('ContactDB Organisation Index'),
|
||||
'description' => __('A list of organisations known by your Cerebrate instance. This list can get populated either directly, by adding new organisations or by fetching them from trusted remote sources.'),
|
||||
'includeAllPagination' => true,
|
||||
'actions' => [
|
||||
[
|
||||
'url' => '/organisations/view',
|
||||
|
|
|
@ -77,6 +77,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('Roles Index'),
|
||||
'description' => __('A list of configurable user roles. Create or modify user access roles based on the settings below.'),
|
||||
'includeAllPagination' => true,
|
||||
'pull' => 'right',
|
||||
'actions' => [
|
||||
[
|
||||
|
|
|
@ -57,6 +57,7 @@ echo $this->element('genericElements/IndexTable/index_table', [
|
|||
],
|
||||
'title' => __('Sharing Groups Index'),
|
||||
'description' => __('Sharing groups are distribution lists usable by tools that can exchange information with a list of trusted partners. Create recurring or ad hoc sharing groups and share them with the members of the sharing group.'),
|
||||
'includeAllPagination' => true,
|
||||
'pull' => 'right',
|
||||
'actions' => [
|
||||
[
|
||||
|
|
|
@ -56,7 +56,7 @@ class BroodsFixture extends TestFixture
|
|||
'id' => self::BROOD_WIREMOCK_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'wiremock',
|
||||
'url' => 'http://localhost:8080',
|
||||
'url' => sprintf('http://%s:%s', $_ENV['WIREMOCK_HOST'] ?? 'localhost', $_ENV['WIREMOCK_PORT'] ?? '8080'),
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'trusted' => true,
|
||||
|
|
|
@ -11,8 +11,8 @@ class InboxFixture extends TestFixture
|
|||
public $connection = 'test';
|
||||
public $table = 'inbox';
|
||||
|
||||
public const INBOX_USER_REGISTRATION_ID = 1;
|
||||
public const INBOX_INCOMING_CONNECTION_REQUEST_ID = 2;
|
||||
public const INBOX_USER_REGISTRATION_UUID = 'e783b13a-7019-48f5-848e-582bb930a833';
|
||||
public const INBOX_INCOMING_CONNECTION_REQUEST_UUID = '9810bd94-16f9-42e0-b364-af59dba50a34';
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
|
@ -20,8 +20,7 @@ class InboxFixture extends TestFixture
|
|||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::INBOX_USER_REGISTRATION_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'uuid' => self::INBOX_USER_REGISTRATION_UUID,
|
||||
'scope' => 'User',
|
||||
'action' => 'Registration',
|
||||
'title' => 'User account creation requested for foo@bar.com',
|
||||
|
@ -37,15 +36,14 @@ class InboxFixture extends TestFixture
|
|||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INBOX_INCOMING_CONNECTION_REQUEST_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'uuid' => self::INBOX_INCOMING_CONNECTION_REQUEST_UUID,
|
||||
'scope' => 'LocalTool',
|
||||
'action' => 'IncomingConnectionRequest',
|
||||
'title' => 'Request for MISP Inter-connection',
|
||||
'origin' => 'http://127.0.0.1',
|
||||
'comment' => null,
|
||||
'description' => 'Handle Phase I of inter-connection when another cerebrate instance performs the request.',
|
||||
'user_id' => UsersFixture::USER_ORG_ADMIN_ID,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'data' => [
|
||||
'connectorName' => 'MispConnector',
|
||||
'cerebrateURL' => 'http://127.0.0.1',
|
||||
|
|
|
@ -15,6 +15,7 @@ class IndividualsFixture extends TestFixture
|
|||
public const INDIVIDUAL_ORG_ADMIN_ID = 3;
|
||||
public const INDIVIDUAL_REGULAR_USER_ID = 4;
|
||||
public const INDIVIDUAL_A_ID = 5;
|
||||
public const INDIVIDUAL_B_ID = 6;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
|
@ -70,6 +71,16 @@ class IndividualsFixture extends TestFixture
|
|||
'position' => 'user',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INDIVIDUAL_B_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'email' => $faker->email(),
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'position' => 'user',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class MetaTemplateDirectoryFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const META_TEMPLATE_DIRECTORY_ID = 1;
|
||||
public const META_TEMPLATE_DIRECTORY_UUID = '99c7b7c0-23e2-4ba8-9ad4-97bcdadf4c81';
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::META_TEMPLATE_DIRECTORY_ID,
|
||||
'uuid' => self::META_TEMPLATE_DIRECTORY_UUID,
|
||||
'name' => 'Test Meta Template Directory',
|
||||
'namespace' => 'cerebrate',
|
||||
'version' => '1'
|
||||
]
|
||||
];
|
||||
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ class MetaTemplateFieldsFixture extends TestFixture
|
|||
'field' => 'test_field_1',
|
||||
'type' => 'text',
|
||||
'meta_template_id' => MetaTemplatesFixture::ENABLED_TEST_ORG_META_TEMPLATE_ID,
|
||||
'meta_template_directory_id' => MetaTemplateDirectoryFixture::META_TEMPLATE_DIRECTORY_ID,
|
||||
'regex' => null,
|
||||
'multiple' => 1,
|
||||
'enabled' => 1,
|
||||
|
|
|
@ -44,6 +44,7 @@ class MetaTemplatesFixture extends TestFixture
|
|||
$this->records = [
|
||||
[
|
||||
'id' => self::ENABLED_TEST_ORG_META_TEMPLATE_ID,
|
||||
'meta_template_directory_id' => MetaTemplateDirectoryFixture::META_TEMPLATE_DIRECTORY_ID,
|
||||
'scope' => 'organisation',
|
||||
'name' => 'Test Meta Template (enabled)',
|
||||
'namespace' => 'cerebrate',
|
||||
|
@ -58,6 +59,7 @@ class MetaTemplatesFixture extends TestFixture
|
|||
],
|
||||
[
|
||||
'id' => self::DISABLED_TEST_ORG_META_TEMPLATE_ID,
|
||||
'meta_template_directory_id' => MetaTemplateDirectoryFixture::META_TEMPLATE_DIRECTORY_ID,
|
||||
'scope' => 'organisation',
|
||||
'name' => 'Test Meta Template (disabled)',
|
||||
'namespace' => 'cerebrate',
|
||||
|
|
|
@ -15,16 +15,18 @@ trait WireMockTestTrait
|
|||
private $wiremock;
|
||||
|
||||
/** @var array<mixed> */
|
||||
private $config = [
|
||||
'hostname' => 'localhost',
|
||||
'port' => 8080
|
||||
];
|
||||
private $config;
|
||||
|
||||
public function initializeWireMock(): void
|
||||
{
|
||||
$this->config = [
|
||||
'hostname' => $_ENV['WIREMOCK_HOST'] ?? 'localhost',
|
||||
'port' => $_ENV['WIREMOCK_PORT'] ?? 8080
|
||||
];
|
||||
|
||||
$this->wiremock = WireMock::create(
|
||||
$_ENV['WIREMOCK_HOST'] ?? $this->config['hostname'],
|
||||
$_ENV['WIREMOCK_PORT'] ?? $this->config['port']
|
||||
$this->config['hostname'],
|
||||
$this->config['port']
|
||||
);
|
||||
|
||||
if (!$this->wiremock->isAlive()) {
|
||||
|
|
|
@ -59,6 +59,7 @@ $ vendor/bin/phpunit --testsuite=api --testdox
|
|||
Available suites:
|
||||
* `app`: runs all test suites
|
||||
* `api`: runs only api tests
|
||||
* `e2e`: runs only integration tests (requires wiremock running)
|
||||
* `controller`: runs only controller tests
|
||||
* _to be continued ..._
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class IndexInboxApiTest extends TestCase
|
|||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', InboxFixture::INBOX_USER_REGISTRATION_ID));
|
||||
$this->assertResponseContains(sprintf('"id": %d', InboxFixture::INBOX_INCOMING_CONNECTION_REQUEST_ID));
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', InboxFixture::INBOX_USER_REGISTRATION_UUID));
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', InboxFixture::INBOX_INCOMING_CONNECTION_REQUEST_UUID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,20 +31,20 @@ class MispInterConnectionTest extends TestCase
|
|||
];
|
||||
|
||||
/** constants related to the local Cerebrate instance */
|
||||
private const LOCAL_CEREBRATE_URL = 'http://127.0.0.1';
|
||||
private const LOCAL_CEREBRATE_URL = 'http://localhost';
|
||||
|
||||
/** constants related to the local MISP instance */
|
||||
private const LOCAL_MISP_INSTANCE_URL = 'http://localhost:8080/MISP_LOCAL';
|
||||
private const LOCAL_MISP_INSTANCE_URL = '/MISP_LOCAL';
|
||||
private const LOCAL_MISP_ADMIN_USER_AUTHKEY = 'b17ce79ac0f05916f382ab06ea4790665dbc174c';
|
||||
|
||||
/** constants related to the remote Cerebrate instance */
|
||||
private const REMOTE_CEREBRATE_URL = 'http://127.0.0.1:8080/CEREBRATE_REMOTE';
|
||||
private const REMOTE_CEREBRATE_URL = '/CEREBRATE_REMOTE';
|
||||
private const REMOTE_CEREBRATE_AUTHKEY = 'a192ba3c749b545f9cec6b6bba0643736f6c3022';
|
||||
|
||||
/** constants related to the remote MISP instance */
|
||||
private const REMOTE_MISP_SYNC_USER_ID = 333;
|
||||
private const REMOTE_MISP_SYNC_USER_EMAIL = 'sync@misp.remote';
|
||||
private const REMOTE_MISP_INSTANCE_URL = 'http://localhost:8080/MISP_REMOTE';
|
||||
private const REMOTE_MISP_INSTANCE_URL = '/MISP_REMOTE';
|
||||
private const REMOTE_MISP_AUTHKEY = '19ca57ecebd2fe34c1c17d729980678eb648d541';
|
||||
|
||||
|
||||
|
@ -64,7 +64,7 @@ class MispInterConnectionTest extends TestCase
|
|||
'name' => 'MISP_LOCAL',
|
||||
'connector' => 'MispConnector',
|
||||
'settings' => json_encode([
|
||||
'url' => self::LOCAL_MISP_INSTANCE_URL,
|
||||
'url' => $this->getWireMockBaseUrl() . self::LOCAL_MISP_INSTANCE_URL,
|
||||
'authkey' => self::LOCAL_MISP_ADMIN_USER_AUTHKEY,
|
||||
'skip_ssl' => true,
|
||||
]),
|
||||
|
@ -90,7 +90,7 @@ class MispInterConnectionTest extends TestCase
|
|||
[
|
||||
'uuid' => $LOCAL_BROOD_UUID,
|
||||
'name' => 'Local Brood',
|
||||
'url' => self::REMOTE_CEREBRATE_URL,
|
||||
'url' => $this->getWireMockBaseUrl() . self::REMOTE_CEREBRATE_URL,
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'trusted' => true,
|
||||
|
@ -228,10 +228,10 @@ class MispInterConnectionTest extends TestCase
|
|||
[
|
||||
'email' => self::REMOTE_MISP_SYNC_USER_EMAIL,
|
||||
'authkey' => self::REMOTE_MISP_AUTHKEY,
|
||||
'url' => self::REMOTE_MISP_INSTANCE_URL,
|
||||
'url' => $this->getWireMockBaseUrl() . self::REMOTE_MISP_INSTANCE_URL,
|
||||
'reflected_user_id' => self::REMOTE_MISP_SYNC_USER_ID,
|
||||
'connectorName' => 'MispConnector',
|
||||
'cerebrateURL' => self::REMOTE_CEREBRATE_URL,
|
||||
'cerebrateURL' => $this->getWireMockBaseUrl() . self::REMOTE_CEREBRATE_URL,
|
||||
'local_tool_id' => 1,
|
||||
'remote_tool_id' => 1,
|
||||
'tool_name' => 'MISP_REMOTE'
|
||||
|
@ -250,7 +250,7 @@ class MispInterConnectionTest extends TestCase
|
|||
self::LOCAL_MISP_ADMIN_USER_AUTHKEY,
|
||||
[
|
||||
'authkey' => self::REMOTE_MISP_AUTHKEY,
|
||||
'url' => self::REMOTE_MISP_INSTANCE_URL,
|
||||
'url' => $this->getWireMockBaseUrl() . self::REMOTE_MISP_INSTANCE_URL,
|
||||
'name' => 'MISP_REMOTE',
|
||||
'remote_org_id' => OrganisationsFixture::ORGANISATION_A_ID
|
||||
]
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace App\Test\TestCase\Api\Users;
|
|||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Fixture\IndividualsFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\RolesFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
@ -31,18 +31,20 @@ class AddUserApiTest extends TestCase
|
|||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'individual_id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'individual_id' => IndividualsFixture::INDIVIDUAL_B_ID,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
|
||||
'disabled' => false,
|
||||
'username' => 'test',
|
||||
'username' => 'test123',
|
||||
'password' => 'Password123456!',
|
||||
]
|
||||
);
|
||||
|
||||
print_r($this->getJsonResponseAsArray());
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"username": "test"');
|
||||
$this->assertDbRecordExists('Users', ['username' => 'test']);
|
||||
$this->assertResponseContains('"username": "test123"');
|
||||
$this->assertDbRecordExists('Users', ['username' => 'test123']);
|
||||
}
|
||||
|
||||
public function testAddUserNotAllowedAsRegularUser(): void
|
||||
|
@ -51,7 +53,7 @@ class AddUserApiTest extends TestCase
|
|||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'individual_id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'individual_id' => IndividualsFixture::INDIVIDUAL_B_ID,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
|
||||
'disabled' => false,
|
||||
|
@ -61,6 +63,6 @@ class AddUserApiTest extends TestCase
|
|||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('Users', ['username' => 'test']);
|
||||
$this->assertDbRecordNotExists('Users', ['username' => 'test123']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
|
@ -25,6 +26,7 @@ class DeleteUserApiTest extends TestCase
|
|||
|
||||
public function testDeleteUser(): void
|
||||
{
|
||||
Configure::write('user.allow-user-deletion', true);
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
|
||||
$this->delete($url);
|
||||
|
|
|
@ -40,14 +40,12 @@ class ApplicationTest extends IntegrationTestCase
|
|||
$app->bootstrap();
|
||||
$plugins = $app->getPlugins();
|
||||
|
||||
$this->assertCount(7, $plugins);
|
||||
$this->assertSame('Bake', $plugins->get('Bake')->getName());
|
||||
$this->assertSame('DebugKit', $plugins->get('DebugKit')->getName());
|
||||
$this->assertSame('Migrations', $plugins->get('Migrations')->getName());
|
||||
$this->assertSame('Authentication', $plugins->get('Authentication')->getName());
|
||||
$this->assertSame('ADmad/SocialAuth', $plugins->get('ADmad/SocialAuth')->getName());
|
||||
$this->assertSame('Tags', $plugins->get('Tags')->getName());
|
||||
$this->assertSame('Cake/TwigView', $plugins->get('Cake/TwigView')->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Integration\Broods;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\BroodsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
use App\Test\Helper\WireMockTestTrait;
|
||||
use \WireMock\Client\WireMock;
|
||||
|
||||
class TestBroodConnectionApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
use WireMockTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/broods/testConnection';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testTestBroodConnection(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->initializeWireMock();
|
||||
$stub = $this->mockCerebrateStatusResponse();
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_WIREMOCK_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->verifyStubCalled($stub);
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"user": "wiremock"');
|
||||
}
|
||||
|
||||
private function mockCerebrateStatusResponse(): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::get(WireMock::urlEqualTo('/instance/status.json'))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
"version" => "0.1",
|
||||
"application" => "Cerebrate",
|
||||
"user" => [
|
||||
"id" => 1,
|
||||
"username" => "wiremock",
|
||||
"role" => [
|
||||
"id" => 1
|
||||
]
|
||||
]
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,405 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Integration\LocalTools;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Fixture\RolesFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
use App\Test\Helper\WireMockTestTrait;
|
||||
use \WireMock\Client\WireMock;
|
||||
|
||||
class MispInterConnectionTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
use WireMockTestTrait;
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods',
|
||||
'app.LocalTools',
|
||||
'app.RemoteToolConnections',
|
||||
'app.Inbox'
|
||||
];
|
||||
|
||||
/** constants related to the local Cerebrate instance */
|
||||
private const LOCAL_CEREBRATE_URL = 'http://localhost';
|
||||
|
||||
/** constants related to the local MISP instance */
|
||||
private const LOCAL_MISP_INSTANCE_URL = '/MISP_LOCAL';
|
||||
private const LOCAL_MISP_ADMIN_USER_AUTHKEY = 'b17ce79ac0f05916f382ab06ea4790665dbc174c';
|
||||
|
||||
/** constants related to the remote Cerebrate instance */
|
||||
private const REMOTE_CEREBRATE_URL = '/CEREBRATE_REMOTE';
|
||||
private const REMOTE_CEREBRATE_AUTHKEY = 'a192ba3c749b545f9cec6b6bba0643736f6c3022';
|
||||
|
||||
/** constants related to the remote MISP instance */
|
||||
private const REMOTE_MISP_SYNC_USER_ID = 333;
|
||||
private const REMOTE_MISP_SYNC_USER_EMAIL = 'sync@misp.remote';
|
||||
private const REMOTE_MISP_INSTANCE_URL = '/MISP_REMOTE';
|
||||
private const REMOTE_MISP_AUTHKEY = '19ca57ecebd2fe34c1c17d729980678eb648d541';
|
||||
|
||||
|
||||
public function testInterConnectMispViaCerebrate(): void
|
||||
{
|
||||
$this->initializeWireMock();
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
/**
|
||||
* 1. Create LocalTool connection to `MISP LOCAL` (local MISP instance)
|
||||
*/
|
||||
$this->post(
|
||||
sprintf('%s/localTools/add', self::LOCAL_CEREBRATE_URL),
|
||||
[
|
||||
'name' => 'MISP_LOCAL',
|
||||
'connector' => 'MispConnector',
|
||||
'settings' => json_encode([
|
||||
'url' => $this->getWireMockBaseUrl() . self::LOCAL_MISP_INSTANCE_URL,
|
||||
'authkey' => self::LOCAL_MISP_ADMIN_USER_AUTHKEY,
|
||||
'skip_ssl' => true,
|
||||
]),
|
||||
'description' => 'MISP local instance',
|
||||
'exposed' => true
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('LocalTools', ['name' => 'MISP_LOCAL']);
|
||||
|
||||
/**
|
||||
* 2. Create a new Brood (connect to a remote Cerebrate instance)
|
||||
* This step assumes that the remote Cerebrate instance is already
|
||||
* running and has a user created for the local Cerebrate instance.
|
||||
*
|
||||
* NOTE: Uses OrganisationsFixture::ORGANISATION_A_ID from the
|
||||
* fixtures as the local Organisation.
|
||||
*/
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$LOCAL_BROOD_UUID = $faker->uuid;
|
||||
$this->post(
|
||||
'/broods/add',
|
||||
[
|
||||
'uuid' => $LOCAL_BROOD_UUID,
|
||||
'name' => 'Local Brood',
|
||||
'url' => $this->getWireMockBaseUrl() . self::REMOTE_CEREBRATE_URL,
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'trusted' => true,
|
||||
'pull' => true,
|
||||
'skip_proxy' => true,
|
||||
'authkey' => self::REMOTE_CEREBRATE_AUTHKEY,
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('Broods', ['uuid' => $LOCAL_BROOD_UUID]);
|
||||
$brood = $this->getJsonResponseAsArray();
|
||||
|
||||
/**
|
||||
* 3. Create a new Cerebrate local user for the remote Cerebrate
|
||||
* These includes:
|
||||
* - 3.a: Create a new Organisation
|
||||
* - 3.b: Create a new Individual
|
||||
* - 3.c: Create a new User
|
||||
* - 3.d: Create a new Authkey
|
||||
*/
|
||||
// Create Organisation
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$remoteOrgUuid = $faker->uuid;
|
||||
$this->post(
|
||||
'/organisations/add',
|
||||
[
|
||||
'name' => 'Remote Organisation',
|
||||
'description' => $faker->text,
|
||||
'uuid' => $remoteOrgUuid,
|
||||
'url' => 'http://cerebrate.remote',
|
||||
'nationality' => 'US',
|
||||
'sector' => 'sector',
|
||||
'type' => 'type',
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('Organisations', ['uuid' => $remoteOrgUuid]);
|
||||
$remoteOrg = $this->getJsonResponseAsArray();
|
||||
|
||||
// Create Individual
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->post(
|
||||
'/individuals/add',
|
||||
[
|
||||
'email' => 'sync@cerebrate.remote',
|
||||
'first_name' => 'Remote',
|
||||
'last_name' => 'Cerebrate'
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('Individuals', ['email' => 'sync@cerebrate.remote']);
|
||||
$remoteIndividual = $this->getJsonResponseAsArray();
|
||||
|
||||
// Create User
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->post(
|
||||
'/users/add',
|
||||
[
|
||||
'individual_id' => $remoteIndividual['id'],
|
||||
'organisation_id' => $remoteOrg['id'],
|
||||
'role_id' => RolesFixture::ROLE_SYNC_ID,
|
||||
'disabled' => false,
|
||||
'username' => 'remote_cerebrate',
|
||||
'password' => 'Password123456!',
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('Users', ['username' => 'remote_cerebrate']);
|
||||
$user = $this->getJsonResponseAsArray();
|
||||
|
||||
// Create Authkey
|
||||
$remoteCerebrateAuthkey = $faker->sha1;
|
||||
$remoteAuthkeyUuid = $faker->uuid;
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->post(
|
||||
'/authKeys/add',
|
||||
[
|
||||
'uuid' => $remoteAuthkeyUuid,
|
||||
'authkey' => $remoteCerebrateAuthkey,
|
||||
'expiration' => 0,
|
||||
'user_id' => $user['id'],
|
||||
'comment' => $faker->text
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('AuthKeys', ['uuid' => $remoteAuthkeyUuid]);
|
||||
|
||||
/**
|
||||
* 4. Get remote Cerebrate exposed tools
|
||||
*/
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->mockCerebrateGetExposedToolsResponse('CEREBRATE_REMOTE', self::REMOTE_CEREBRATE_AUTHKEY);
|
||||
$this->get(sprintf('/localTools/broodTools/%s', $brood['id']));
|
||||
$this->assertResponseOk();
|
||||
$tools = $this->getJsonResponseAsArray();
|
||||
|
||||
/**
|
||||
* 5. Issue a connection request to the remote MISP instance
|
||||
*/
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->mockCerebrateGetExposedToolsResponse('CEREBRATE_REMOTE', self::REMOTE_CEREBRATE_AUTHKEY);
|
||||
$this->mockMispViewOrganisationByUuid(
|
||||
'MISP_LOCAL',
|
||||
self::LOCAL_MISP_ADMIN_USER_AUTHKEY,
|
||||
OrganisationsFixture::ORGANISATION_A_UUID,
|
||||
OrganisationsFixture::ORGANISATION_A_ID
|
||||
);
|
||||
$this->mockMispCreateSyncUser(
|
||||
'MISP_LOCAL',
|
||||
self::LOCAL_MISP_ADMIN_USER_AUTHKEY,
|
||||
self::REMOTE_MISP_SYNC_USER_ID,
|
||||
self::REMOTE_MISP_SYNC_USER_EMAIL
|
||||
);
|
||||
$this->mockCerebrateCreateMispIncommingConnectionRequest(
|
||||
'CEREBRATE_REMOTE',
|
||||
UsersFixture::USER_ADMIN_ID,
|
||||
self::LOCAL_CEREBRATE_URL,
|
||||
self::REMOTE_CEREBRATE_AUTHKEY,
|
||||
self::LOCAL_MISP_INSTANCE_URL
|
||||
);
|
||||
$this->post(
|
||||
sprintf('/localTools/connectionRequest/%s/%s', $brood['id'], $tools[0]['id']),
|
||||
[
|
||||
'local_tool_id' => 1
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
|
||||
/**
|
||||
* 6. Remote Cerebrate accepts the connection request
|
||||
*/
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->post(
|
||||
'/inbox/createEntry/LocalTool/AcceptedRequest',
|
||||
[
|
||||
'email' => self::REMOTE_MISP_SYNC_USER_EMAIL,
|
||||
'authkey' => self::REMOTE_MISP_AUTHKEY,
|
||||
'url' => $this->getWireMockBaseUrl() . self::REMOTE_MISP_INSTANCE_URL,
|
||||
'reflected_user_id' => self::REMOTE_MISP_SYNC_USER_ID,
|
||||
'connectorName' => 'MispConnector',
|
||||
'cerebrateURL' => $this->getWireMockBaseUrl() . self::REMOTE_CEREBRATE_URL,
|
||||
'local_tool_id' => 1,
|
||||
'remote_tool_id' => 1,
|
||||
'tool_name' => 'MISP_REMOTE'
|
||||
]
|
||||
);
|
||||
$this->assertResponseOk();
|
||||
$acceptRequest = $this->getJsonResponseAsArray();
|
||||
|
||||
/**
|
||||
* 7. Finalize the connection
|
||||
*/
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->mockEnableMispSyncUser('MISP_LOCAL', self::LOCAL_MISP_ADMIN_USER_AUTHKEY, self::REMOTE_MISP_SYNC_USER_ID);
|
||||
$this->mockAddMispServer(
|
||||
'MISP_LOCAL',
|
||||
self::LOCAL_MISP_ADMIN_USER_AUTHKEY,
|
||||
[
|
||||
'authkey' => self::REMOTE_MISP_AUTHKEY,
|
||||
'url' => $this->getWireMockBaseUrl() . self::REMOTE_MISP_INSTANCE_URL,
|
||||
'name' => 'MISP_REMOTE',
|
||||
'remote_org_id' => OrganisationsFixture::ORGANISATION_A_ID
|
||||
]
|
||||
);
|
||||
$this->post(sprintf('/inbox/process/%s', $acceptRequest['data']['id']));
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"success": true');
|
||||
$this->verifyAllStubsCalled();
|
||||
}
|
||||
|
||||
private function mockCerebrateGetExposedToolsResponse(string $instance, string $cerebrateAuthkey): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::get(WireMock::urlEqualTo("/$instance/localTools/exposedTools"))
|
||||
->withHeader('Authorization', WireMock::equalTo($cerebrateAuthkey))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
[
|
||||
"id" => 1,
|
||||
"name" => "MISP ($instance)",
|
||||
"connector" => "MispConnector",
|
||||
]
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
private function mockMispViewOrganisationByUuid(string $instance, string $mispAuthkey, string $orgUuid, int $orgId): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::get(WireMock::urlEqualTo("/$instance/organisations/view/$orgUuid/limit:50"))
|
||||
->withHeader('Authorization', WireMock::equalTo($mispAuthkey))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
"Organisation" => [
|
||||
"id" => $orgId,
|
||||
"name" => $instance . ' Organisation',
|
||||
"uuid" => $orgUuid,
|
||||
"local" => true
|
||||
]
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
private function mockMispCreateSyncUser(string $instance, string $mispAuthkey, int $userId, string $email): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::post(WireMock::urlEqualTo("/$instance/admin/users/add"))
|
||||
->withHeader('Authorization', WireMock::equalTo($mispAuthkey))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
"User" => [
|
||||
"id" => $userId,
|
||||
"email" => $email,
|
||||
"authkey" => $faker->sha1
|
||||
]
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
private function mockCerebrateCreateMispIncommingConnectionRequest(
|
||||
string $instance,
|
||||
int $userId,
|
||||
string $cerebrateUrl,
|
||||
string $cerebrateAuthkey,
|
||||
string $mispUrl
|
||||
): \WireMock\Stubbing\StubMapping {
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::post(WireMock::urlEqualTo("/$instance/inbox/createEntry/LocalTool/IncomingConnectionRequest"))
|
||||
->withHeader('Authorization', WireMock::equalTo($cerebrateAuthkey))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
'data' => [
|
||||
'id' => $faker->randomNumber(),
|
||||
'uuid' => $faker->uuid,
|
||||
'origin' => $cerebrateUrl,
|
||||
'user_id' => $userId,
|
||||
'data' => [
|
||||
'connectorName' => 'MispConnector',
|
||||
'cerebrateURL' => $cerebrateUrl,
|
||||
'url' => $mispUrl,
|
||||
'tool_connector' => 'MispConnector',
|
||||
'local_tool_id' => 1,
|
||||
'remote_tool_id' => 1,
|
||||
],
|
||||
'title' => 'Request for MISP Inter-connection',
|
||||
'scope' => 'LocalTool',
|
||||
'action' => 'IncomingConnectionRequest',
|
||||
'description' => 'Handle Phase I of inter-connection when another cerebrate instance performs the request.',
|
||||
'local_tool_connector_name' => 'MispConnector',
|
||||
'created' => date('c'),
|
||||
'modified' => date('c')
|
||||
],
|
||||
'success' => true,
|
||||
'message' => 'LocalTool request for IncomingConnectionRequest created',
|
||||
'errors' => [],
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
private function mockEnableMispSyncUser(string $instance, string $mispAuthkey, int $userId): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::post(WireMock::urlEqualTo("/$instance/admin/users/edit/$userId"))
|
||||
->withHeader('Authorization', WireMock::equalTo($mispAuthkey))
|
||||
->withRequestBody(WireMock::equalToJson(json_encode(['disabled' => false])))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
"User" => [
|
||||
"id" => $userId,
|
||||
]
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
private function mockAddMispServer(string $instance, string $mispAuthkey, array $body): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::post(WireMock::urlEqualTo("/$instance/servers/add"))
|
||||
->withHeader('Authorization', WireMock::equalTo($mispAuthkey))
|
||||
->withRequestBody(WireMock::equalToJson(json_encode($body)))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode(
|
||||
[
|
||||
'Server' => [
|
||||
'id' => $faker->randomNumber()
|
||||
]
|
||||
]
|
||||
)))
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue