acquia_connector_test.module in Acquia Connector 7.2
Same filename and directory in other branches
Test endpoint for Acquia Connector XML-RPC calls.
File
acquia_agent/tests/acquia_connector_test.moduleView source
<?php
include_once DRUPAL_ROOT . '/includes/xmlrpc.inc';
include_once DRUPAL_ROOT . '/includes/xmlrpcs.inc';
/**
* @file
* Test endpoint for Acquia Connector XML-RPC calls.
*/
define('ACQTEST_SUBSCRIPTION_NOT_FOUND', 1000);
define('ACQTEST_SUBSCRIPTION_KEY_MISMATCH', 1100);
define('ACQTEST_SUBSCRIPTION_EXPIRED', 1200);
define('ACQTEST_SUBSCRIPTION_REPLAY_ATTACK', 1300);
define('ACQTEST_SUBSCRIPTION_KEY_NOT_FOUND', 1400);
define('ACQTEST_SUBSCRIPTION_MESSAGE_FUTURE', 1500);
define('ACQTEST_SUBSCRIPTION_MESSAGE_EXPIRED', 1600);
define('ACQTEST_SUBSCRIPTION_MESSAGE_INVALID', 1700);
define('ACQTEST_SUBSCRIPTION_VALIDATION_ERROR', 1800);
define('ACQTEST_SUBSCRIPTION_SITE_NOT_FOUND', 1900);
define('ACQTEST_SUBSCRIPTION_PROVISION_ERROR', 9000);
define('ACQTEST_SUBSCRIPTION_MESSAGE_LIFETIME', 15 * 60);
define('ACQTEST_EMAIL', 'TEST_networkuser@example.com');
define('ACQTEST_PASS', 'TEST_password');
define('ACQTEST_ID', 'TEST_AcquiaConnectorTestID');
define('ACQTEST_KEY', 'TEST_AcquiaConnectorTestKey');
define('ACQTEST_ERROR_ID', 'TEST_AcquiaConnectorTestIDErr');
define('ACQTEST_ERROR_KEY', 'TEST_AcquiaConnectorTestKeyErr');
define('ACQTEST_EXPIRED_ID', 'TEST_AcquiaConnectorTestIDExp');
define('ACQTEST_EXPIRED_KEY', 'TEST_AcquiaConnectorTestKeyExp');
define('ACQTEST_503_ID', 'TEST_AcquiaConnectorTestID503');
define('ACQTEST_503_KEY', 'TEST_AcquiaConnectorTestKey503');
if (!defined('ACQUIA_DEVELOPMENT_NOSSL')) {
define('ACQUIA_DEVELOPMENT_NOSSL', TRUE);
}
function acquia_connector_test_xmlrpc() {
return array(
array(
'acquia.agent.validate',
'acquia_connector_test_validate',
array(
'boolean',
'array',
),
t('Test validates an Acquia Network authenticator.'),
),
array(
'acquia.agent.subscription',
'acquia_connector_test_subscription',
array(
'struct',
'array',
),
t('Test validates an Acquia Network subscription.'),
),
array(
'acquia.agent.mail.exists',
'acquia_connector_test_mail_exists',
array(
'boolean',
'array',
),
t('Test returns TRUE if the e-mail address matches a registered user'),
),
array(
'acquia.agent.provision.get_user_details',
'acquia_connector_test_provision_get_user_details',
array(
'struct',
'array',
),
t('Test returns details of an existing user.'),
),
array(
'acquia.agent.communication.settings',
'acquia_connector_test_get_communication_settings',
array(
'struct',
'array',
),
t('Test return communication settings for an account.'),
),
array(
'acquia.agent.subscription.credentials',
'acquia_connector_test_credentials',
array(
'struct',
'array',
),
t('Test returns subscriptions for an email.'),
),
array(
'acquia.agent.subscription.name',
'acquia_connector_test_subscription_name',
array(
'struct',
'array',
),
t('Test returns subscription name for an indentifer.'),
),
array(
'acquia.agent.cloud.migration.environments',
'acquia_connector_test_cloud_migration_environments',
array(
'struct',
'array',
),
t('Test returns environments available for site import.'),
),
array(
'acquia.agent.cloud.migration.complete',
'acquia_connector_test_migration_complete',
array(
'struct',
'array',
),
t('Test complete final migration'),
),
array(
'acquia.nspi.update',
'acquia_connector_test_nspi_update',
array(
'array',
'array',
),
t('Test incoming site profile information.'),
),
);
}
function acquia_connector_test_menu() {
$items['spi_def/get/%'] = array(
'page callback' => 'acquia_connector_test_spi_definition',
'page arguments' => array(
2,
),
'access callback' => TRUE,
);
$items['system/acquia-connector-test-upload'] = array(
'page callback' => 'acquia_connector_test_upload',
'access callback' => TRUE,
);
return $items;
}
function acquia_connector_test_spi_definition($arg_version) {
$vars = array(
'file_temporary_path' => array(
'optional' => FALSE,
'description' => 'file_temporary_path',
),
'page_compression' => array(
'optional' => TRUE,
'description' => 'page_compression',
),
'user_admin_role' => array(
'optional' => TRUE,
'description' => 'user_admin_role',
),
);
$data = array(
'drupal_version' => $arg_version,
'timestamp' => (string) (REQUEST_TIME + 9),
'acquia_spi_variables' => $vars,
);
drupal_json_output($data);
}
function acquia_connector_test_upload() {
$data = 'invalid request';
$response_code = 400;
if (variable_get('acquia_connector_test_upload_server_to_fail', FALSE)) {
$data = '';
$response_code = 500;
}
return (object) array(
'data' => $data,
'code' => $response_code,
);
}
function acquia_connector_test_validate($data) {
$result = acquia_connector_test_validate_authenticator($data);
if (empty($result->is_error)) {
return TRUE;
}
unset($result->secret);
xmlrpc_error($result->code, $result->message);
}
function acquia_connector_test_subscription($data) {
$result = acquia_connector_test_validate_authenticator($data);
if (empty($result->is_error)) {
$result->authenticator['hash'] = _acquia_agent_hmac($result->secret['key'], $result->authenticator['time'], $result->authenticator['nonce'], $result->body);
unset($result->secret);
return (array) $result;
}
unset($result->secret);
xmlrpc_error($result->code, $result->message);
}
function acquia_connector_test_mail_exists($data) {
// return object
}
function acquia_connector_test_provision_get_user_details($data) {
// return object
}
function acquia_connector_test_get_communication_settings($data) {
// Authenticate.
$fields = array(
'time' => 'is_numeric',
'nonce' => 'is_string',
'hash' => 'is_string',
);
$result = acquia_connector_test_basic_authenticator($fields, $data);
if (!empty($result->is_error)) {
return $result;
}
if (!isset($data['body']) || !isset($data['body']['email'])) {
return xmlrpc_error(ACQSUBSCRIPTION_VALIDATION_ERROR, t('Invalid arguments'));
}
$account = user_load_by_mail($data['body']['email']);
if (empty($account) || $account->uid == 0) {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Account not found'));
}
else {
$result = array(
'algorithm' => 'sha512',
'hash_setting' => substr($account->pass, 0, 12),
'extra_md5' => FALSE,
);
return $result;
}
return TRUE;
}
function acquia_connector_test_credentials($data) {
$fields = array(
'time' => 'is_numeric',
'nonce' => 'is_string',
'hash' => 'is_string',
);
$result = acquia_connector_test_basic_authenticator($fields, $data);
if (!empty($result->is_error)) {
return $result;
}
if (!empty($data['body']['email'])) {
$account = user_load_by_mail($data['body']['email']);
if (empty($account) || $account->uid == 0) {
return xmlrpc_error(ACQSUBSCRIPTION_VALIDATION_ERROR, t('Account not found'));
}
}
else {
return xmlrpc_error(ACQSUBSCRIPTION_VALIDATION_ERROR, t('Invalid arguments'));
}
$hash = _acquia_agent_hmac($account->pass, $data['authenticator']['time'], $data['authenticator']['nonce'], $data['body']);
if ($hash === $data['authenticator']['hash']) {
$result = array();
$result['is_error'] = FALSE;
$result['body']['subscription'][] = array(
'identifier' => ACQTEST_ID,
'key' => ACQTEST_KEY,
'name' => ACQTEST_ID,
);
return $result;
}
else {
return xmlrpc_error(ACQSUBSCRIPTION_VALIDATION_ERROR, t('Incorrect password.'));
}
}
function acquia_connector_test_subscription_name($data) {
$fields = array(
'time' => 'is_numeric',
'nonce' => 'is_string',
'hash' => 'is_string',
);
$result = acquia_connector_test_basic_authenticator($fields, $data);
if (!empty($result->is_error)) {
return $result;
}
if (!empty($data['body']['identifier'])) {
if (strpos($data['body']['identifier'], 'TEST_') !== 0) {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Subscription not found'));
}
$result = array();
$result['is_error'] = FALSE;
$result['body']['subscription'] = array(
'site_name' => $data['body']['identifier'],
);
return $result;
}
else {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Invalid arguments'));
}
}
function acquia_connector_test_cloud_migration_environments($data) {
$fields = array(
'time' => 'is_numeric',
'nonce' => 'is_string',
'hash' => 'is_string',
);
$result = acquia_connector_test_basic_authenticator($fields, $data);
if (!empty($result->is_error)) {
return $result;
}
if (!empty($data['body']['identifier'])) {
if (strpos($data['body']['identifier'], 'TEST_') !== 0) {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Subscription not found'));
}
}
else {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Invalid arguments'));
}
if ($data['body']['identifier'] == ACQTEST_ERROR_ID) {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_SITE_NOT_FOUND, t("Hosting not available under your subscription. Upgrade your subscription to continue with import."));
}
$result = array();
$result['is_error'] = FALSE;
foreach (array(
'dev' => 'Development',
'test' => 'Stage',
'prod' => 'Production',
) as $key => $name) {
$result['body']['environments'][$key] = array(
'url' => url('system/acquia-connector-test-upload/AH_UPLOAD', array(
'absolute' => TRUE,
)),
'stage' => $key,
'nonce' => 'nonce',
'secret' => 'secret',
'site_name' => $name,
);
}
return $result;
}
function acquia_connector_test_migration_complete($data) {
// return array
}
function acquia_connector_test_nspi_update($data) {
$fields = array(
'time' => 'is_numeric',
'nonce' => 'is_string',
'hash' => 'is_string',
);
$result = acquia_connector_test_basic_authenticator($fields, $data);
if (!empty($result->is_error)) {
return $result;
}
if (!empty($data['authenticator']['identifier'])) {
if ($data['authenticator']['identifier'] != ACQTEST_ID && $data['authenticator']['identifier'] != ACQTEST_ERROR_ID) {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Subscription not found'));
}
if ($data['authenticator']['identifier'] == ACQTEST_ERROR_ID) {
return FALSE;
}
else {
$result = acquia_connector_test_validate_authenticator($data);
$spi_data = $data['body'];
$result->body = array(
'spi_data_received' => TRUE,
);
if (isset($spi_data['spi_def_update'])) {
$result->body['update_spi_definition'] = TRUE;
}
// Reflect send_method as nspi_messages if set.
if (isset($spi_data['send_method'])) {
$result->body['nspi_messages'][] = $spi_data['send_method'];
}
$result->authenticator['hash'] = _acquia_agent_hmac($result->secret['key'], $result->authenticator['time'], $result->authenticator['nonce'], $result->body);
if (isset($spi_data['test_validation_error'])) {
$result->authenticator['nonce'] = 'TEST';
// Force a validation fail.
}
unset($result->secret);
return (array) $result;
}
}
else {
return xmlrpc_error(ACQTEST_SUBSCRIPTION_VALIDATION_ERROR, t('Invalid arguments'));
}
}
function acquia_connector_test_basic_authenticator($fields, $data) {
$result = new stdClass();
foreach ($fields as $field => $type) {
if (empty($data['authenticator'][$field]) || !$type($data['authenticator'][$field])) {
$result->code = ACQTEST_SUBSCRIPTION_MESSAGE_INVALID;
$result->message = t('Authenticator field @field is missing or invalid.', array(
'@field' => $field,
));
$result->is_error = TRUE;
return $result;
}
}
$now = REQUEST_TIME;
if ($data['authenticator']['time'] > $now + ACQTEST_SUBSCRIPTION_MESSAGE_LIFETIME) {
$result->code = ACQTEST_SUBSCRIPTION_MESSAGE_FUTURE;
$result->message = t('Message time ahead of server time.');
$result->is_error = TRUE;
return $result;
}
else {
if ($data['authenticator']['time'] < $now - ACQTEST_SUBSCRIPTION_MESSAGE_LIFETIME) {
$result->code = ACQTEST_SUBSCRIPTION_MESSAGE_EXPIRED;
$result->message = t('Message is too old.');
$result->is_error = TRUE;
return $result;
}
}
$result->is_error = FALSE;
return $result;
}
function acquia_connector_test_validate_authenticator($data) {
$fields = array(
'time' => 'is_numeric',
'identifier' => 'is_string',
'nonce' => 'is_string',
'hash' => 'is_string',
);
$result = acquia_connector_test_basic_authenticator($fields, $data);
if (!empty($result->is_error)) {
return $result;
}
if (strpos($data['authenticator']['identifier'], 'TEST_') !== 0) {
$result->code = ACQTEST_SUBSCRIPTION_NOT_FOUND;
$result->message = t('Subscription not found.');
$result->is_error = TRUE;
return $result;
}
switch ($data['authenticator']['identifier']) {
case ACQTEST_ID:
$key = ACQTEST_KEY;
break;
case ACQTEST_EXPIRED_ID:
$key = ACQTEST_EXPIRED_KEY;
break;
case ACQTEST_503_ID:
$key = ACQTEST_503_KEY;
break;
default:
$key = ACQTEST_ERROR_KEY;
break;
}
$hash = _acquia_agent_hmac($key, $data['authenticator']['time'], $data['authenticator']['nonce'], $data['body']);
$hash_simple = _acquia_agent_hmac($key, $data['authenticator']['time'], $data['authenticator']['nonce'], array());
if ($hash !== $data['authenticator']['hash'] && $hash_simple != $data['authenticator']['hash']) {
$result->code = ACQTEST_SUBSCRIPTION_VALIDATION_ERROR;
$result->message = t('HMAC validation error: ') . "{$hash} != {$data['authenticator']['hash']}";
$result->is_error = TRUE;
return $result;
}
if ($key === ACQTEST_EXPIRED_KEY) {
$result->code = ACQTEST_SUBSCRIPTION_EXPIRED;
$result->message = t('Subscription expired.');
$result->is_error = TRUE;
return $result;
}
// Record connections.
$connections = variable_get('acquia_connector_test_connections' . $data['authenticator']['identifier'], 0);
$connections++;
variable_set('acquia_connector_test_connections' . $data['authenticator']['identifier'], $connections);
if ($connections == 3 && $data['authenticator']['identifier'] == ACQTEST_503_ID) {
$result->code = 9999;
$result->message = t('General error.');
$result->is_error = TRUE;
return $result;
}
$result->is_error = FALSE;
$result->body['active'] = 1;
$result->body['href'] = 'TEST';
$result->body['expiration_date']['value'] = '2023-10-08T06:30:00';
$result->body['product'] = '91990';
$result->body['derived_key_salt'] = $data['authenticator']['identifier'] . '_KEY_SALT';
$result->body['update_service'] = 1;
$result->body['search_service_enabled'] = 1;
if (isset($data['body']['rpc_version'])) {
$result->body['rpc_version'] = $data['body']['rpc_version'];
}
$result->secret['data'] = $data;
$result->secret['nid'] = '91990';
$result->secret['node'] = $data['authenticator']['identifier'] . '_NODE';
$result->secret['key'] = $key;
$result->authenticator = $data['authenticator'];
$result->authenticator['hash'] = '';
$result->authenticator['time'] += 1;
return $result;
}
function _acquia_connector_test_increment_requests() {
$requests = variable_get('acquia_connector_test-requests', 0);
$requests++;
variable_set('acquia_connector_test-requests', $requests);
}
function acquia_connector_test_xmlrpc_server_emulator($method, $data) {
_acquia_connector_test_increment_requests();
$result = array();
switch ($method) {
case 'acquia.agent.communication.settings':
$result = acquia_connector_test_get_communication_settings($data);
break;
case 'acquia.agent.subscription.credentials':
$result = acquia_connector_test_credentials($data);
break;
case 'acquia.agent.subscription.name':
$result = acquia_connector_test_subscription_name($data);
break;
case 'acquia.agent.validate':
$result = acquia_connector_test_validate($data);
break;
case 'acquia.agent.subscription':
$result = acquia_connector_test_subscription($data);
break;
case 'acquia.agent.cloud.migration.environments':
$result = acquia_connector_test_cloud_migration_environments($data);
break;
case 'acquia.agent.cloud.migration.complete':
$result = acquia_connector_test_migration_complete($data);
break;
case 'acquia.nspi.update':
$result = acquia_connector_test_nspi_update($data);
break;
}
if (xmlrpc_errno()) {
return FALSE;
}
return $result;
}