Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion adapters/stormshield/conf/device.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ model.name = Generic
manufacturer.id = 16010401
manufacturer.name = Stormshield
manufacturer.category = Security
feature.restore = false
feature.restore = true
obsolete = false
39 changes: 23 additions & 16 deletions adapters/stormshield/connect.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
require_once 'smsd/sms_common.php';
require_once 'smsd/expect.php';
require_once 'smsd/generic_connection.php';

require_once load_once('stormshield', 'nsrpc.php');

require_once "$db_objects";

class connect extends GenericConnection {
Expand All @@ -21,6 +24,7 @@ class connect extends GenericConnection {
private $response;
private $cookie;
private $session_id;
private $curl_cmd;

public function __construct($ip = null, $login = null, $passwd = null, $admin_password = null, $port = null)
{
Expand Down Expand Up @@ -117,15 +121,6 @@ public function send($origin, $rest_cmd) {

$url = "https://{$this->sd_ip_config}/{$rest_path}";

$headers = '';
foreach ($this->http_header_list as $header) {
$H = trim($header);
$headers .= " -H '{$H}'";
}

// for debug
$curl_cmd = "curl -X {$http_op} {$headers} --connect-timeout {$this->conn_timeout} --max-time {$this->conn_timeout} -k '{$url}'";

if (count($cmd_list) > 2) {
if (isset($this->session_id)) {
$payload = $cmd_list[2];
Expand Down Expand Up @@ -157,14 +152,25 @@ public function send($origin, $rest_cmd) {
$rest_payload = '';
}

$curl_cmd .= " --data-raw '{$rest_payload}'";
$this->execute_curl_command($origin, $http_op, $url, $rest_payload);

debug_dump($curl_cmd, "HTTP REQUEST:\n");
$this->execute_curl_command($origin, $http_op, $url, $rest_payload, $curl_cmd);
debug_dump($this->response, "HTTP RESPONSE:\n");
$ret = is_error_xml($this->response);
if ($ret !== false)
{
throw new SmsException("Response to API {$this->curl_cmd} Failed: \n$ret", ERR_SD_CMDFAILED, $origin);
}
}

private function execute_curl_command($origin, $http_op, $url, $rest_payload, $curl_cmd) {
private function execute_curl_command($origin, $http_op, $url, $rest_payload) {

// for debug
$headers = '';
foreach ($this->http_header_list as $h) {
$H = trim($h);
$headers .= " -H '{$H}'";
}
$this->curl_cmd = "curl -X {$http_op} {$headers} --connect-timeout {$this->conn_timeout} --max-time {$this->conn_timeout} -k '{$url}' --data-raw '{$rest_payload}'";
debug_dump($this->curl_cmd, "HTTP REQUEST:\n");

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
Expand Down Expand Up @@ -206,7 +212,7 @@ private function execute_curl_command($origin, $http_op, $url, $rest_payload, $c
if ($http_code < 200 || $http_code > 209) {
$cmd_quote = str_replace("\"", "'", $body);
$cmd_return = str_replace("\n", "", $cmd_quote);
throw new SmsException("Call to API {$curl_cmd} Failed, header = $header, $cmd_return error", ERR_SD_CMDFAILED, $origin);
throw new SmsException("Call to API {$this->curl_cmd} Failed, header = $header, $cmd_return error", ERR_SD_CMDFAILED, $origin);
}

if (!isset($this->cookie)) {
Expand All @@ -221,9 +227,10 @@ private function execute_curl_command($origin, $http_op, $url, $rest_payload, $c
else
{
if ($http_code != 204) {
throw new SmsException ("$origin: Response to API {$curl_cmd} Failed, expected json received empty response, header $header", ERR_SD_CMDFAILED);
throw new SmsException ("$origin: Response to API {$this->curl_cmd} Failed, expected json received empty response, header $header", ERR_SD_CMDFAILED);
}
}
debug_dump($this->response, "HTTP RESPONSE:\n");
}
}

Expand Down
4 changes: 2 additions & 2 deletions adapters/stormshield/connect_cli.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public function do_connect() {
}

public function do_disconnect() {
$this->sendexpectone(__FILE__.':'.__LINE__, "quit", '>');
$this->sendCmd(__FILE__.':'.__LINE__, 'exit');
//$this->sendexpectone(__FILE__.':'.__LINE__, "quit", '>');
//$this->sendCmd(__FILE__.':'.__LINE__, 'exit');
parent::disconnect();
}

Expand Down
2 changes: 1 addition & 1 deletion adapters/stormshield/do_get_archive_conf.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

echo "/opt/sms/bin/sms_scp_transfer -r -s $local_backup -d $target_file -a $sd->SD_IP_CONFIG -l $sd->SD_LOGIN_ENTRY -p '$sd->SD_PASSWD_ENTRY' -P $sd->SD_MANAGEMENT_PORT\n";

$ret_scp = exec_local(__FILE__.':'.__LINE__, "/opt/sms/bin/sms_scp_transfer -r -s $local_backup -d $target_file -a $sd->SD_IP_CONFIG -l $sd->SD_LOGIN_ENTRY -p '$sd->SD_PASSWD_ENTRY' -P $sd->SD_MANAGEMENT_PORT", $output);
exec_local(__FILE__.':'.__LINE__, "/opt/sms/bin/sms_scp_transfer -r -s $local_backup -d $target_file -a $sd->SD_IP_CONFIG -l $sd->SD_LOGIN_ENTRY -p '$sd->SD_PASSWD_ENTRY' -P $sd->SD_MANAGEMENT_PORT", $output);

// remove the backup on the ME
connect();
Expand Down
173 changes: 153 additions & 20 deletions adapters/stormshield/do_restore_conf.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,136 @@
*/

// Restore configuration from archive file
// TODO

require_once 'smsd/sms_common.php';

require_once load_once('stormshield', 'netasq_configuration.php');
require_once load_once('stormshield', 'connect_cli.php');
require_once load_once('stormshield', 'nsrpc.php');

function get_old_revision($restore_conf_file, $revision_id)
{
global $sdid;

echo("restore_from_old_revision revision_id: $revision_id\n");

$get_saved_conf_cmd = "/opt/sms/script/get_saved_conf --getfile {$sdid} file {$restore_conf_file} r{$revision_id}";

$ret = exec_local(__FILE__ . ':' . __LINE__, $get_saved_conf_cmd, $output);
if ($ret !== SMS_OK)
{
echo("no running conf found\n");
unlink($restore_conf_file);
return $ret;
}

if (!file_exists($restore_conf_file))
{
echo("no running conf found\n");
return ERR_CONFIG_EMPTY;
}

return SMS_OK;
}

function copy_restore_file_to_me($sd, $src, $dst)
{
global $sms_sd_ctx;

$ret = SMS_OK;

echo "/opt/sms/bin/sms_scp_transfer -s $src -d $dst -a $sd->SD_IP_CONFIG -l $sd->SD_LOGIN_ENTRY -p '$sd->SD_PASSWD_ENTRY' -P $sd->SD_MANAGEMENT_PORT\n";

exec_local(__FILE__.':'.__LINE__, "/opt/sms/bin/sms_scp_transfer -s $src -d $dst -a $sd->SD_IP_CONFIG -l $sd->SD_LOGIN_ENTRY -p '$sd->SD_PASSWD_ENTRY' -P $sd->SD_MANAGEMENT_PORT", $output);
// no check ot the outcome, will check the presence of the file on the ME later on

// remove the backup on the MSA
unlink($src);

// check file on ME
connect();

sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "quit", '>');
$result = sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "test -f $dst; echo $?", '>');
if (strpos($result, "\n0") === false)
{
$err = __FILE__ . ':' . __LINE__ . ": Impossible to copy restore file from $src to $dst\n";
sms_log_error("$err\n");
$ret = ERR_SD_CMDFAILED;
}

disconnect();

return $ret;
}

function restore_conf($sd, $restore_conf_file)
{
global $sms_sd_ctx;

connect();

sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "modify on force");

$ret = sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "config restore list=\"all\" refresh=1 < $restore_conf_file");

sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "quit", '>');
sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "rm $restore_conf_file", '>');

if (is_error($ret))
{
$err = __FILE__ . ':' . __LINE__ . ": Error config restore list=\"all\" refresh=1 < $restore_conf_file returns\n$ret";
sms_log_error("$err\n");
disconnect();
return ERR_SD_CMDFAILED;
}

// reboot
sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, 'cli', 'assword');
sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, $sd->SD_PASSWD_ENTRY);
sendexpectone(__FILE__.':'.__LINE__, $sms_sd_ctx, "system reboot", '>');

disconnect();

return SMS_OK;
}

function wait_until_device_is_up($sd, $nb_loop = 60, $initial_sec_to_wait = 30)
{
// wait the device become up after reboot
$ret = wait_for_device_up($sd->SD_IP_CONFIG, $nb_loop, $initial_sec_to_wait);
if ($ret != SMS_OK)
{
return $ret;
}

sms_sleep($initial_sec_to_wait); // Wait for the ssh service
$done = $nb_loop;
do
{
echo "waiting for the device (SSH), $done\n";
sleep(5);
try
{
connect();
break;
}
catch (Exception | Error $e)
{
$done--;
}
} while ($done > 0);

if ($done === 0)
{
sms_log_error(__FILE__ . ':' . __LINE__ . ": The device stay DOWN\n");
return ERR_SD_CMDTMOUT;
}

disconnect();

return SMS_OK;
}


$ret = sms_sd_lock($sms_csp, $sms_sd_info);
if ($ret !== 0)
Expand All @@ -37,39 +162,47 @@

// Asynchronous mode, the user socket is now closed, the results are written in database

$network = get_network_profile();
$sd = &$network->SD;

try
{
netasq_connect();

$conf = new netasq_configuration($sdid);
$restore_conf_file = "{$sdid}_r{$revision_id}.conf";
$msa_restore_conf_file = "/opt/sms/spool/tmp/{$restore_conf_file}";

// Should be connected before calling restore_from_old_revision
// After restore_from_old_revision is called, we are disconnected
$ret = $conf->restore_from_old_revision($revision_id);
$ret = get_old_revision($msa_restore_conf_file, $revision_id);
if ($ret !== SMS_OK)
{
sms_set_update_status($sms_csp, $sdid, $ret, 'RESTORE', 'FAILED', "Restoring revision $revision_id failed");
sms_set_update_status($sms_csp, $sdid, $ret, 'RESTORE', 'FAILED', "Getting revision $revision_id failed");
sms_sd_unlock($sms_csp, $sms_sd_info);
return SMS_OK;
}

sms_set_update_status($sms_csp, $sdid, SMS_OK, 'RESTORE', 'WORKING', "Waiting the device (restore revision: $revision_id)");
$ret = $conf->wait_until_device_is_up(60, 0);
if ($ret !== SMS_OK)
$me_restore_conf_file = "/tmp/{$restore_conf_file}";

$ret = copy_restore_file_to_me($sd, $msa_restore_conf_file, $me_restore_conf_file);
if ($ret != SMS_OK)
{
sms_set_update_status($sms_csp, $sdid, $ret, 'RESTORE', 'FAILED', "The device is unreachable after restoring the configuration (restore revision: $revision_id)");
sms_set_update_status($sms_csp, $sdid, $ret, 'RESTORE', 'FAILED', "Copying revision $revision_id failed");
sms_sd_unlock($sms_csp, $sms_sd_info);
return SMS_OK;
}

if ($conf->sd->SD_HSRP_TYPE !== 0)
$ret = restore_conf($sd, $me_restore_conf_file);
if ($ret != SMS_OK)
{
netasq_connect();

sms_set_update_status($sms_csp, $sdid, SMS_OK, 'RESTORE', 'WORKING', "Synchronize the configuration on the passive node (restore revision: $revision_id)");
$ret = $conf->ha_sync();
sms_set_update_status($sms_csp, $sdid, $ret, 'RESTORE', 'FAILED', "Restoring revision $revision_id failed");
sms_sd_unlock($sms_csp, $sms_sd_info);
return SMS_OK;
}

netasq_disconnect();
sms_set_update_status($sms_csp, $sdid, SMS_OK, 'RESTORE', 'WORKING', "Waiting the device (restore revision: $revision_id)");
$ret = wait_until_device_is_up($sd);
if ($ret !== SMS_OK)
{
sms_set_update_status($sms_csp, $sdid, $ret, 'RESTORE', 'FAILED', "The device is unreachable after restoring the configuration (restore revision: $revision_id)");
sms_sd_unlock($sms_csp, $sms_sd_info);
return SMS_OK;
}

sms_set_update_status($sms_csp, $sdid, SMS_OK, 'RESTORE', 'WORKING', "Backup of the restored configuration (restore revision: $revision_id)");
Expand All @@ -80,7 +213,7 @@
}
catch (Exception | Error $e)
{
netasq_disconnect();
disconnect();
sms_set_update_status($sms_csp, $sdid, $e->getCode(), 'RESTORE', 'FAILED', "Restore failure (restore revision: $revision_id)");
sms_sd_unlock($sms_csp, $sms_sd_info);
return SMS_OK;
Expand Down
Loading