AWS Credentials support, StaticCredentials Provider (#17)

* added credentials API, disabled FFI backend for now

* Added CredentialsTest

* Added support for specifying CMAKE_BUILD_TYPE on the command line

* Added support for AwsCredentials and StaticCredentialsProvider
This commit is contained in:
Justin Boswell
2021-03-17 13:59:05 -04:00
committed by GitHub
parent 9171857448
commit 73ecd3bc8a
16 changed files with 585 additions and 86 deletions
+68
View File
@@ -0,0 +1,68 @@
<?php
namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource as NativeResource;
use AWS\CRT\Options as Options;
/**
* Represents a set of AWS credentials
*
* @param array options:
* - string access_key_id - AWS Access Key Id
* - string secret_access_key - AWS Secret Access Key
* - string session_token - Optional STS session token
* - int expiration_timepoint_seconds - Optional time to expire these credentials
*/
final class AwsCredentials extends NativeResource {
static function defaults() {
return array(
'access_key_id' => '',
'secret_access_key' => '',
'session_token' => '',
'expiration_timepoint_seconds' => 0,
);
}
private $access_key_id;
private $secret_access_key;
private $session_token;
private $expiration_timepoint_seconds = 0;
public function __get($name) {
return $this->$name;
}
function __construct($options = []) {
parent::__construct();
if (count($options) == 0) {
$options = self::defaults();
}
$options = new Options($options);
$this->access_key_id = $options->getString('access_key_id');
$this->secret_access_key = $options->getString('secret_access_key');
$this->session_token = $options->getString('session_token');
$this->expiration_timepoint_seconds = $options->getInt('expiration_timepoint_seconds');
if (strlen($this->access_key_id) == 0) {
throw new \InvalidArgumentException("access_key_id must be provided");
}
if (strlen($this->secret_access_key) == 0) {
throw new \InvalidArgumentException("secret_access_key must be provided");
}
$creds_options = self::$crt->aws_credentials_options_new();
self::$crt->aws_credentials_options_set_access_key_id($creds_options, $this->access_key_id);
self::$crt->aws_credentials_options_set_secret_access_key($creds_options, $this->secret_access_key);
self::$crt->aws_credentials_options_set_session_token($creds_options, $this->session_token);
self::$crt->aws_credentials_options_set_expiration_timepoint_seconds($creds_options, $this->expiration_timepoint_seconds);
$this->acquire(self::$crt->aws_credentials_new($creds_options));
self::$crt->aws_credentials_options_release($creds_options);
}
function __destruct() {
self::$crt->aws_credentials_release($this->release());
parent::__destruct();
}
}
+20
View File
@@ -0,0 +1,20 @@
<?php
namespace AWS\CRT\Auth;
use AWS\CRT\NativeResource as NativeResource;
/**
* Base class for credentials providers
*/
abstract class CredentialsProvider extends NativeResource {
function __construct(array $options = []) {
parent::__construct();
}
function __destruct() {
self::$crt->aws_credentials_provider_release($this->release());
parent::__destruct();
}
}
@@ -0,0 +1,43 @@
<?php
namespace AWS\CRT\Auth;
/**
* Provides a static set of AWS credentials
*
* @param array options:
* - string access_key_id - AWS Access Key Id
* - string secret_access_key - AWS Secret Access Key
* - string session_token - Optional STS session token
*/
final class StaticCredentialsProvider extends CredentialsProvider {
static function defaults() {
return array(
'access_key_id' => '',
'secret_access_key' => '',
'session_token' => '',
);
}
private $credentials = null;
public function __get($name) {
return $this->$name;
}
function __construct(array $options = []) {
parent::__construct();
if (count($options) == 0) {
$options = self::defaults();
}
$this->credentials = new AwsCredentials($options);
$provider_options = self::$crt->aws_credentials_provider_static_options_new();
self::$crt->aws_credentials_provider_static_options_set_access_key_id($provider_options, $this->credentials->access_key_id);
self::$crt->aws_credentials_provider_static_options_set_secret_access_key($provider_options, $this->credentials->secret_access_key);
self::$crt->aws_credentials_provider_static_options_set_session_token($provider_options, $this->credentials->session_token);
$this->acquire(self::$crt->aws_credentials_provider_static_new($provider_options));
self::$crt->aws_credentials_provider_static_options_release($provider_options);
}
}
+63 -9
View File
@@ -3,7 +3,6 @@
namespace AWS\CRT;
use AWS\CRT\Internal\Extension;
use AWS\CRT\Internal\FFI;
use \RuntimeException;
@@ -22,14 +21,6 @@ final class CRT {
if (is_null(self::$impl)) {
// Figure out what backends are/should be available
$backends = ['Extension'];
if (version_compare(PHP_VERSION, '7.0.0') >= 0) {
$backends = ['Extension', 'FFI'];
if (getenv('AWS_CRT_PHP_EXTENSION')) {
$backends = ['Extension'];
} else if (getenv('AWS_CRT_PHP_FFI')) {
$backends = ['FFI'];
}
}
// Try to load each backend, give up if none succeed
$exceptions = [];
@@ -113,4 +104,67 @@ final class CRT {
function event_loop_group_release($elg) {
return self::$impl->aws_crt_event_loop_group_release($elg);
}
/**
* return object Pointer to native AWS credentials options
*/
function aws_credentials_options_new() {
return self::$impl->aws_crt_credentials_options_new();
}
function aws_credentials_options_release($options) {
self::$impl->aws_crt_credentials_options_release($options);
}
function aws_credentials_options_set_access_key_id($options, $access_key_id) {
self::$impl->aws_crt_credentials_options_set_access_key_id($options, $access_key_id);
}
function aws_credentials_options_set_secret_access_key($options, $secret_access_key) {
self::$impl->aws_crt_credentials_options_set_secret_access_key($options, $secret_access_key);
}
function aws_credentials_options_set_session_token($options, $session_token) {
self::$impl->aws_crt_credentials_options_set_session_token($options, $session_token);
}
function aws_credentials_options_set_expiration_timepoint_seconds($options, $expiration_timepoint_seconds) {
self::$impl->aws_crt_credentials_options_set_expiration_timepoint_seconds($options, $expiration_timepoint_seconds);
}
function aws_credentials_new($options) {
return self::$impl->aws_crt_credentials_new($options);
}
function aws_credentials_release($credentials) {
self::$impl->aws_crt_credentials_release($credentials);
}
function aws_credentials_provider_release($provider) {
self::$impl->aws_crt_credentials_provider_release($provider);
}
function aws_credentials_provider_static_options_new() {
return self::$impl->aws_crt_credentials_provider_static_options_new();
}
function aws_credentials_provider_static_options_release($options) {
self::$impl->aws_crt_credentials_provider_static_options_release($options);
}
function aws_credentials_provider_static_options_set_access_key_id($options, $access_key_id) {
self::$impl->aws_crt_credentials_provider_static_options_set_access_key_id($options, $access_key_id);
}
function aws_credentials_provider_static_options_set_secret_access_key($options, $secret_access_key) {
self::$impl->aws_crt_credentials_provider_static_options_set_secret_access_key($options, $secret_access_key);
}
function aws_credentials_provider_static_options_set_session_token($options, $session_token) {
self::$impl->aws_crt_credentials_provider_static_options_set_session_token($options, $session_token);
}
function aws_credentials_provider_static_new($options) {
return self::$impl->aws_crt_credentials_provider_static_new($options);
}
}
+4 -2
View File
@@ -3,6 +3,7 @@
namespace AWS\CRT\IO;
use AWS\CRT\NativeResource as NativeResource;
use AWS\CRT\Options as Options;
/**
* Represents 1 or more event loops (1 per thread) for doing I/O and background tasks.
@@ -19,13 +20,14 @@ final class EventLoopGroup extends NativeResource {
);
}
function __construct(array $options = array()) {
function __construct(array $options = []) {
parent::__construct();
if (count($options) == 0) {
$options = self::defaults();
}
$options = new Options($options);
$elg_options = self::$crt->event_loop_group_options_new();
self::$crt->event_loop_group_options_set_max_threads($elg_options, $options['max_threads']);
self::$crt->event_loop_group_options_set_max_threads($elg_options, $options->getInt('max_threads'));
$this->acquire(self::$crt->event_loop_group_new($elg_options));
self::$crt->event_loop_group_options_release($elg_options);
}
-51
View File
@@ -1,51 +0,0 @@
<?php
namespace AWS\CRT\Internal;
use \Exception;
use \RuntimeException;
/**
* @internal
* Forwards calls on to libaws-crt-ffi via FFI
*/
final class FFI {
private static $ffi = null;
private static $refcount = 0;
function __construct() {
if (is_null(self::$ffi)) {
try {
self::$ffi = \FFI::cdef(file_get_contents(__DIR__ . "/../../../api.h"), __DIR__ . "/../../../libaws-crt-ffi.so");
self::init();
} catch (Exception $e) {
throw new RuntimeException('Exception while initializing CRT via FFI', 0, $e);
}
}
++self::$refcount;
}
function __destruct() {
if (--self::$refcount == 0) {
self::clean_up();
self::$ffi = null;
}
}
/**
* Forwards any call made on this object to the FFI function of the
* same name with the supplied arguments. Argument type hinting and checking
* occurs at the CRT wrapper.
*/
function __call(string $name, $args) {
return call_user_func_array(array(self::$ffi, $name), $args);
}
private static function init() {
return self::$ffi->aws_crt_init();
}
private static function clean_up() {
return self::$ffi->aws_crt_clean_up();
}
}
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace AWS\CRT;
final class Options {
private $options = [];
public function __construct($opts = []) {
$this->options = $opts;
}
public function __get($name) {
return (isset($this->options[$name])) ? $this->options[$name] : null;
}
public function asArray() {
return $this->options;
}
public function toArray() {
return array_merge_recursive([], $this->options);
}
public function getInt($name) {
$val = $this->$name;
return (is_null($val)) ? 0 : (int)$val;
}
public function getString($name) {
return !empty($this->options[$name]) ? strval($this->options[$name]) : "";
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
use AWS\CRT\Auth\AwsCredentials as AwsCredentials;
use AWS\CRT\Auth\StaticCredentialsProvider as StaticCredentialsProvider;
require_once('common.inc');
final class CredentialsTest extends CrtTestCase {
public function testEmptyCredentials() {
$this->expectException(InvalidArgumentException::class);
$creds = new AwsCredentials(AwsCredentials::defaults());
$this->assertNotNull($creds, "Failed to create default/empty credentials");
$creds = null;
}
private function getCredentialsConfig() {
$options = AwsCredentials::defaults();
$options['access_key_id'] = 'TESTAWSACCESSKEYID';
$options['secret_access_key'] = 'TESTSECRETaccesskeyThatDefinitelyDoesntWork';
$options['session_token'] = 'ThisIsMyTestSessionTokenIMadeItUpMyself';
$options['expiration_timepoint_seconds'] = 42;
return $options;
}
public function testCredentialsLifetime() {
$options = $this->getCredentialsConfig();
$creds = new AwsCredentials($options);
$this->assertNotNull($creds, "Failed to create Credentials with options");
$this->assertEquals($creds->access_key_id, $options['access_key_id']);
$this->assertEquals($creds->secret_access_key, $options['secret_access_key']);
$this->assertEquals($creds->session_token, $options['session_token']);
$this->assertEquals($creds->expiration_timepoint_seconds, $options['expiration_timepoint_seconds']);
$creds = null;
}
public function testStaticCredentialsProviderLifetime() {
$options = $this->getCredentialsConfig();
$provider = new StaticCredentialsProvider($options);
$this->assertNotNull($provider, "Failed to create StaticCredentialsProvider");
$provider = null;
}
}
+3 -1
View File
@@ -2,7 +2,9 @@
use AWS\CRT\IO\EventLoopGroup as EventLoopGroup;
final class EventLoopGroupTest extends PHPUnit_Framework_TestCase {
require_once('common.inc');
final class EventLoopGroupTest extends CrtTestCase {
public function testLifetime() {
$elg = new EventLoopGroup();
+12
View File
@@ -0,0 +1,12 @@
<?php
use AWS\CRT\CRT as CRT;
abstract class CrtTestCase extends PHPUnit_Framework_TestCase {
// Ensure that after every test there are no errors in the CRT itself
protected function assertPostConditions() {
if (CRT::last_error()) {
$this->fail("Test left an error on the stack: " . CRT::error_name(CRT::last_error()));
}
}
}