<?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) { $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"; $canonical_request = $a['method'] . "\n" . '/' . urlencode($a['file']) . "\n" . "\n" . $iheaders_final . $iheaders_list . "\n" . bin2hex($a['x-amz-content-sha256']); rg_log_ml('canonical_request:' . "\n" . $canonical_request . "\n" . '==='); $string_to_sign = 'AWS4-HMAC-SHA256' . "\n" . $a['x-amz-date'] . "\n" . gmdate('Ymd', $a['ts']) . '/' . $a['region'] . '/' . $a['service'] . '/' . 'aws4_request' . "\n" . hash('sha256', $canonical_request); rg_log_ml('string_to_sign:' . "\n" . $string_to_sign . "\n" . '==='); $date_key = hash_hmac('sha256', gmdate('Ymd', $a['ts']), 'AWS4' . $a['secret_access_key'], TRUE); $date_region_key = hash_hmac('sha256', $a['region'], $date_key, TRUE); $date_region_service_key = hash_hmac('sha256', $a['service'], $date_region_key, TRUE); $signing_key = hash_hmac('sha256', 'aws4_request', $date_region_service_key, TRUE); $signature = hash_hmac('sha256', $string_to_sign, $signing_key); rg_log('DEBUG: signature=' . $signature); $cred = $a['access_key_id'] . '/' . gmdate('Ymd') . '/' . $a['region'] . '/' . $a['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; } /* * 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) { $url = 'https://' . $a['host'] . '/' . urlencode($a['file']); $c = curl_init($url); if ($c === FALSE) { $ret['error'] = 'cannot init curl'; break; } $a['region'] = trim(strtolower($a['region'])); $a['ts'] = time(); $a['x-amz-date'] = gmdate('Ymd', $a['ts']) . 'T' . gmdate('His', $a['ts']) . 'Z'; $a['x-amz-content-sha256'] = hash('sha256', $a['content'], TRUE); $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']; $a['iheaders']['x-amz-content-sha256'] = bin2hex($a['x-amz-content-sha256']); $auth = rg_amazon_auth($a); if ($auth['ok'] != 1) { $ret['error'] = $auth['error']; break; } $headers = array(); if (isset($a['content_type'])) $headers[] = 'Content-Type: ' . $a['content_type']; $headers[] = 'Authorization: ' . $auth['data']; foreach ($a['iheaders'] as $head => $val) $headers[] = $head . ': ' . $val; //rg_log_ml('HEADERS:' . print_r($headers, TRUE)); curl_setopt($c, CURLOPT_CUSTOMREQUEST, $a['method']); //curl_setopt($c, CURLOPT_POST, 1); curl_setopt($c, CURLOPT_POSTFIELDS, $a['content']); 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('xerr=' . $xerr); } if ($r === FALSE) { $ret['error'] = 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['error'] = $r; break; } $ret['ok'] = 1; $ret['answer'] = $r; break; } curl_close($c); 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['file'] = ''; $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['file'] = '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'); $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) { $a['region'] = ''; $a['access_key_id'] = ''; $a['secret_access_key'] = ''; } ?>