<?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: ' . print_r($a, TRUE)); $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_ml('DEBUG: a[iheaders]: ' . print_r($a['iheaders'], TRUE)); $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_ml('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" . print_r($data, TRUE) . "\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_ml('DEBUG: curl_exec returned: ' . $r); if ($err !== FALSE) { rewind($err); $xerr = @fread($err, 16 * 4096); fclose($err); $ret['debug'] = $xerr; rg_log_ml('DEBUG: xerr=' . "\n" . $xerr); } if ($r === FALSE) { $ret['errmsg'] = curl_error($c); $_info = curl_getinfo($c); rg_log_ml('Debug: ' . print_r($_info, TRUE)); break; } $_info = curl_getinfo($c); rg_log_ml('Debug: ' . print_r($_info, TRUE)); 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_ml('DEBUG: a:' . print_r($a, TRUE)); $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_ml('DEBUG: HEADERS:' . print_r($headers, TRUE)); $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: ' . print_r($a, TRUE)); $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_ml_enter('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_ml_enter('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-Client-Context' => '', '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'] = ''; }