<?php
/*
* Builds the signature for a request
*/
function rg_amazon_auth($a)
{
rg_prof_start('amazon_auth');
rg_log_enter('amazon_auth');
rg_log_ml('a: ' . rg_array2string($a));
$ret = array('ok' => 0);
while (1) {
if (!isset($a['service']))
$service = '';
else
$service = $a['service'];
// Must be ordered!
$ret['query_string'] = '';
if (!isset($a['query_string'])) {
$ret['query_string'] = '';
} else if (is_array($a['query_string'])) {
ksort($a['query_string']);
$add = '';
foreach ($a['query_string'] as $k => $v) {
$ret['query_string'] .= $add
. urlencode($k) . '='
. urlencode($v);
$add = '&';
}
} else {
$ret['query_string'] = $a['query_string'];
}
if (strcmp($a['method'], 'GET') == 0) {
$qs = $ret['query_string'];
$ret['query_string'] = '';
} else {
$qs = '';
}
rg_log_debug('ret[query_string]=' . $ret['query_string']);
if (!empty($a['content'])) {
$a['x-amz-content-sha256'] = hash('sha256', $a['content'], TRUE);
rg_log_debug('a[content] is set to: ' . $a['content']);
$a['iheaders']['x-amz-content-sha256'] =
bin2hex($a['x-amz-content-sha256']);
} else {
$a['x-amz-content-sha256'] = hash('sha256',
$ret['query_string'], TRUE);
rg_log_debug('a[content] is not set');
}
rg_log_debug('a[iheaders]: ' . rg_array2string($a['iheaders']));
$iheaders_final = array();
$iheaders_list = array();
foreach ($a['iheaders'] as $head => $val) {
$iheaders_final[] = strtolower($head)
. ':' . trim($val);
$iheaders_list[] = strtolower($head);
}
asort($iheaders_list);
asort($iheaders_final);
$iheaders_list = implode(';', $iheaders_list);
$iheaders_final = implode("\n", $iheaders_final) . "\n\n";
$ret['iheaders'] = $a['iheaders'];
$canonical_request = $a['method'] . "\n"
. $a['url'] . urlencode($a['file']) . "\n"
. $qs . "\n"
. $iheaders_final
. $iheaders_list . "\n"
. bin2hex($a['x-amz-content-sha256']);
rg_log_debug('canonical_request:' . "\n" . $canonical_request
. "\n" . '===');
$string_to_sign = 'AWS4-HMAC-SHA256' . "\n"
. $a['x-amz-date'] . "\n"
. gmdate('Ymd', $a['ts'])
. '/' . $a['region']
. '/' . $service
. '/' . 'aws4_request'
. "\n"
. hash('sha256', $canonical_request);
rg_log_ml('string_to_sign:' . "\n" . $string_to_sign
. "\n" . '===');
rg_log_debug('secret_access_key=' . $a['secret_access_key'] . '.');
$date_key = hash_hmac('sha256', gmdate('Ymd', $a['ts']),
'AWS4' . $a['secret_access_key'], TRUE);
rg_log_debug('date_key=' . bin2hex($date_key));
$date_region_key = hash_hmac('sha256', $a['region'],
$date_key, TRUE);
rg_log_debug('date_region_key=' . bin2hex($date_region_key));
$date_region_service_key = hash_hmac('sha256',
$service, $date_region_key, TRUE);
rg_log_debug('service=' . $service . ' date_region_service_key=' . bin2hex($date_region_service_key));
$signing_key = hash_hmac('sha256', 'aws4_request',
$date_region_service_key, TRUE);
rg_log_debug('signing_key=' . bin2hex($signing_key));
$signature = hash_hmac('sha256', $string_to_sign, $signing_key);
rg_log_debug('signature=' . $signature);
$cred = $a['access_key_id']
. '/' . gmdate('Ymd', $a['ts'])
. '/' . $a['region']
. '/' . $service
. '/aws4_request';
$ret['data'] = 'AWS4-HMAC-SHA256'
. ' Credential=' . $cred
. ', SignedHeaders=' . $iheaders_list
. ', Signature=' . $signature;
$ret['ok'] = 1;
break;
}
rg_log_exit();
rg_prof_end('amazon_auth');
return $ret;
}
/*
* Generic curl helper
*/
function rg_amazon_curl($url, $method, $headers, $data)
{
rg_log_ml('amazon_curl: data: START' . "\n"
. rg_array2string($data) . "\n" . 'END');
$ret = array('ok' => 0);
while (1) {
if (strcmp($method, 'GET') == 0) {
if (!strstr($url, '?'))
$url .= '?';
$url .= $data;
}
$c = curl_init($url);
if ($c === FALSE) {
$ret['errmsg'] = 'cannot init curl';
break;
}
curl_setopt($c, CURLOPT_CUSTOMREQUEST, $method);
if (strcmp($method, 'GET') != 0) {
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
//curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_HTTPHEADER, $headers);
curl_setopt($c, CURLOPT_USERAGENT, 'RocketGit Cloud client');
curl_setopt($c, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($c, CURLOPT_ENCODING, ''); // => use all methods
curl_setopt($c, CURLOPT_VERBOSE, TRUE);
curl_setopt($c, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
//curl_setopt($c, CURLOPT_CERTINFO, TRUE);
$err = @fopen('php://temp', 'w');
if ($err !== FALSE)
curl_setopt($c, CURLOPT_STDERR, $err);
$r = curl_exec($c);
rg_log_debug('curl_exec returned: ' . $r);
if ($err !== FALSE) {
rewind($err);
$xerr = @fread($err, 16 * 4096);
fclose($err);
$ret['debug'] = $xerr;
rg_log_debug('xerr=' . "\n" . $xerr);
}
if ($r === FALSE) {
$ret['errmsg'] = curl_error($c);
$_info = curl_getinfo($c);
rg_log_debug('_info: ' . rg_array2string($_info));
break;
}
$_info = curl_getinfo($c);
rg_log_debug('_info: ' . rg_array2string($_info));
if (($_info['http_code'] != 200)
&& ($_info['http_code'] != 301)) {
$ret['errmsg'] = $r;
break;
}
$ret['ok'] = 1;
$ret['answer'] = $r;
break;
}
curl_close($c);
return $ret;
}
/*
* Make a generic request to the amazon
*/
function rg_amazon_req($a)
{
rg_prof_start('amazon_req');
rg_log_enter('amazon_req');
rg_log_debug('a:' . rg_array2string($a));
$ret = array('ok' => 0);
while (1) {
if (!isset($a['url']))
$a['url'] = '/';
if (!isset($a['file']))
$a['file'] = '';
if (!empty($a['file']))
$a['file'] = $a['file'];
$url = 'https://' . $a['host'] . $a['url'] . $a['file'];
$a['region'] = trim(strtolower($a['region']));
if (!isset($a['ts']))
$a['ts'] = time();
$a['x-amz-date'] = gmdate('Ymd', $a['ts'])
. 'T' . gmdate('His', $a['ts']) . 'Z';
$a['host'] = trim(strtolower($a['host']));
$a['service'] = trim(strtolower($a['service']));
if (!isset($a['iheaders']))
$a['iheaders'] = array();
$a['iheaders']['Host'] = $a['host'];
$a['iheaders']['x-amz-date'] = $a['x-amz-date'];
$auth = rg_amazon_auth($a);
if ($auth['ok'] != 1) {
$ret['errmsg'] = $auth['error'];
break;
}
$headers = array();
if (isset($a['content_type']))
$headers[] = 'Content-Type: ' . $a['content_type'];
$headers[] = 'Authorization: ' . $auth['data'];
foreach ($auth['iheaders'] as $head => $val)
$headers[] = $head . ': ' . $val;
rg_log_debug('HEADERS:' . rg_array2string($headers));
$ret = rg_amazon_curl($url, $a['method'], $headers,
$a['content']);
break;
}
rg_log_exit();
rg_prof_end('amazon_req');
return $ret;
}
/*
*
* @bucket contains the domain part (s3.amazonaws.com for example)
*/
function rg_amazon_s3_put_object($a, $content)
{
rg_prof_start('amazon_s3_put_object');
rg_log_enter('amazon_s3_put_object');
rg_log_ml('a: ' . rg_array2string($a));
$ret = array('ok' => 0);
while (1) {
$a['service'] = 's3';
$a['method'] = 'PUT';
$a['host'] = $a['bucket'] . '.' . $a['service'] . '.'
. $a['region'] . '.amazonaws.com';
$a['content'] = $content;
$ret = rg_amazon_req($a);
break;
}
rg_log_exit();
rg_prof_end('amazon_s3_put_object');
return $ret;
}
/*
* Create a code deploy
* http://docs.aws.amazon.com/codedeploy/latest/APIReference/API_CreateDeployment.html
*/
function rg_amazon_codedeploy_create($a)
{
rg_prof_start('amazon_codedeploy_create');
rg_log_enter_ml('amazon_codedeploy_create');
if (empty($a['deployment_config_name']))
$a['deployment_config_name'] = 'CodeDeployDefault.OneAtATime';
// do the codedeploy - we may want to add "version" to "s3Location"
$json = '{'
. '"applicationName": ' . rg_json_escape($a['application_name'])
. ', "deploymentGroupName": ' . rg_json_escape($a['deployment_group_name'])
. ', "description": "test description"'
. ', "deploymentConfigName": ' . rg_json_escape($a['deployment_config_name'])
. ', "ignoreApplicationStopFailures": ' . (strchr($a['flags'], 'I') ? 'true' : 'false')
. ', "revision": {'
. '"revisionType": "S3"'
. ', "s3Location": {'
. '"bundleType": "zip"'
. ', "bucket": ' . rg_json_escape($a['bucket'])
. ', "key": ' . rg_json_escape($a['file'])
. '}'
. '}'
. '}';
$ret = array('ok' => 0);
while (1) {
$a['service'] = 'codedeploy';
$a['method'] = 'POST';
$a['host'] = $a['service'] . '.' . $a['region'] . '.amazonaws.com';
$a['iheaders'] = array('x-amz-target' => 'CodeDeploy_20141006.CreateDeployment');
$a['content'] = $json;
$a['content_type'] = 'application/x-amz-json-1.1';
$ret = rg_amazon_req($a);
break;
}
rg_log_exit();
rg_prof_end('amazon_codedeploy_create');
return $ret;
}
/*
* Calls an Amazon Lambda function
* http://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html
*/
function rg_amazon_lambda_invoke($a)
{
rg_prof_start('amazon_lambda_invoke');
rg_log_enter_ml('amazon_lambda_invoke');
if (!isset($a['invocation_type']))
$a['invocation_type'] = 'RequestResponse';
$ret = array('ok' => 0);
while (1) {
$a['service'] = 'lambda';
$a['method'] = 'POST';
$a['url'] = '/2015-03-31/functions/' . $a['function']
. '/invocations';
$a['host'] = $a['service'] . '.' . $a['region'] . '.amazonaws.com';
$a['iheaders'] = array(
'x-Amz-Invocation-Type' => $a['invocation_type'],
'x-Amz-Log-Type' => 'Tail');
$a['content'] = $a['payload'];
$ret = rg_amazon_req($a);
break;
}
rg_log_exit();
rg_prof_end('amazon_lambda_invoke');
return $ret;
}
/*
* Generic cosmetic for Amazon
*/
function rg_wh_amazon_cosmetic(&$row)
{
$a = $row['idata']['access_key_id'];
$row['idata']['HTML:access_key_id_secure'] =
rg_xss_safe(substr($a, 0, 1) . '...' . substr($a, -1, 1));
$a = $row['idata']['secret_access_key'];
$row['idata']['HTML:secret_access_key_secure'] =
rg_xss_safe(substr($a, 0, 1) . '...' . substr($a, -1, 1));
}
/*
* Generic fill_vars for Amazon
*/
function rg_wh_amazon_fill_vars(&$a)
{
$a['access_key_id'] = trim(rg_var_str('wh::idata::access_key_id'));
$a['secret_access_key'] = trim(rg_var_str('wh::idata::secret_access_key'));
$a['region'] = trim(rg_var_str('wh::idata::region'));
}
/*
* Generic validation for Amazon
*/
function rg_wh_amazon_validate_vars($a, &$errmsg)
{
$ret = FALSE;
while (1) {
if (empty($a['access_key_id'])) {
$errmsg[] = rg_template('user/settings/wh/amazon/inv_access_key_id.txt',
$rg, TRUE /*xss*/);
break;
}
if (empty($a['secret_access_key'])) {
$errmsg[] = rg_template('user/settings/wh/amazon/inv_secret_access_key.txt',
$rg, TRUE /*xss*/);
break;
}
if (empty($a['region'])) {
$errmsg[] = rg_template('user/settings/wh/amazon/inv_region.txt',
$rg, TRUE /*xss*/);
break;
}
$ret = TRUE;
break;
}
return $ret;
}
/*
* Generic default_paras for Amazon
*/
function rg_wh_amazon_default_paras(&$a)
{
if (!isset($a['region']))
$a['region'] = '';
if (!isset($a['access_key_id']))
$a['access_key_id'] = '';
if (!isset($a['secret_access_key']))
$a['secret_access_key'] = '';
}