371 lines
8.2 KiB
PHP
371 lines
8.2 KiB
PHP
<?php
|
|
/**
|
|
* Akeeba Engine
|
|
*
|
|
* @package akeebaengine
|
|
* @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
|
|
* @license GNU General Public License version 3, or later
|
|
*/
|
|
|
|
namespace Akeeba\Engine\Postproc\Connector\S3v4;
|
|
|
|
// Protection against direct access
|
|
defined('AKEEBAENGINE') or die();
|
|
|
|
/**
|
|
* Holds the Amazon S3 confiugration credentials
|
|
*/
|
|
class Configuration
|
|
{
|
|
/**
|
|
* Access Key
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $access = '';
|
|
|
|
/**
|
|
* Secret Key
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $secret = '';
|
|
|
|
/**
|
|
* Security token. This is only required with temporary credentials provisioned by an EC2 instance.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $token = '';
|
|
|
|
/**
|
|
* Signature calculation method ('v2' or 'v4')
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $signatureMethod = 'v2';
|
|
|
|
/**
|
|
* AWS region, used for v4 signatures
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $region = 'us-east-1';
|
|
|
|
/**
|
|
* Should I use SSL (HTTPS) to communicate to Amazon S3?
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected $useSSL = true;
|
|
|
|
/**
|
|
* Should I use SSL (HTTPS) to communicate to Amazon S3?
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected $useDualstackUrl = false;
|
|
|
|
/**
|
|
* Should I use legacy, path-style access to the bucket? When it's turned off (default) we use virtual hosting style
|
|
* paths which are RECOMMENDED BY AMAZON per http://docs.aws.amazon.com/AmazonS3/latest/API/APIRest.html
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected $useLegacyPathStyle = false;
|
|
|
|
/**
|
|
* Amazon S3 endpoint. You can use a custom endpoint with v2 signatures to access third party services which offer
|
|
* S3 compatibility, e.g. OwnCloud, Google Storage etc.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $endpoint = 's3.amazonaws.com';
|
|
|
|
/**
|
|
* Public constructor
|
|
*
|
|
* @param string $access Amazon S3 Access Key
|
|
* @param string $secret Amazon S3 Secret Key
|
|
* @param string $signatureMethod Signature method (v2 or v4)
|
|
* @param string $region Region, only required for v4 signatures
|
|
*/
|
|
function __construct(string $access, string $secret, string $signatureMethod = 'v2', string $region = '')
|
|
{
|
|
$this->setAccess($access);
|
|
$this->setSecret($secret);
|
|
$this->setSignatureMethod($signatureMethod);
|
|
$this->setRegion($region);
|
|
}
|
|
|
|
/**
|
|
* Get the Amazon access key
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getAccess(): string
|
|
{
|
|
return $this->access;
|
|
}
|
|
|
|
/**
|
|
* Set the Amazon access key
|
|
*
|
|
* @param string $access The access key to set
|
|
*
|
|
* @throws Exception\InvalidAccessKey
|
|
*/
|
|
public function setAccess(string $access): void
|
|
{
|
|
if (empty($access))
|
|
{
|
|
throw new Exception\InvalidAccessKey;
|
|
}
|
|
|
|
$this->access = $access;
|
|
}
|
|
|
|
/**
|
|
* Get the Amazon secret key
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSecret(): string
|
|
{
|
|
return $this->secret;
|
|
}
|
|
|
|
/**
|
|
* Set the Amazon secret key
|
|
*
|
|
* @param string $secret The secret key to set
|
|
*
|
|
* @throws Exception\InvalidSecretKey
|
|
*/
|
|
public function setSecret(string $secret): void
|
|
{
|
|
if (empty($secret))
|
|
{
|
|
throw new Exception\InvalidSecretKey;
|
|
}
|
|
|
|
$this->secret = $secret;
|
|
}
|
|
|
|
/**
|
|
* Return the security token. Only for temporary credentials provisioned through an EC2 instance.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getToken(): string
|
|
{
|
|
return $this->token;
|
|
}
|
|
|
|
/**
|
|
* Set the security token. Only for temporary credentials provisioned through an EC2 instance.
|
|
*
|
|
* @param string $token
|
|
*/
|
|
public function setToken(string $token): void
|
|
{
|
|
$this->token = $token;
|
|
}
|
|
|
|
/**
|
|
* Get the signature method to use
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getSignatureMethod(): string
|
|
{
|
|
return $this->signatureMethod;
|
|
}
|
|
|
|
/**
|
|
* Set the signature method to use
|
|
*
|
|
* @param string $signatureMethod One of v2 or v4
|
|
*
|
|
* @throws Exception\InvalidSignatureMethod
|
|
*/
|
|
public function setSignatureMethod(string $signatureMethod): void
|
|
{
|
|
$signatureMethod = strtolower($signatureMethod);
|
|
$signatureMethod = trim($signatureMethod);
|
|
|
|
if (!in_array($signatureMethod, ['v2', 'v4']))
|
|
{
|
|
throw new Exception\InvalidSignatureMethod;
|
|
}
|
|
|
|
// If you switch to v2 signatures we unset the region.
|
|
if ($signatureMethod == 'v2')
|
|
{
|
|
$this->setRegion('');
|
|
|
|
/**
|
|
* If we are using Amazon S3 proper (not a custom endpoint) we have to set path style access to false.
|
|
* Amazon S3 does not support v2 signatures with path style access at all (it returns an error telling
|
|
* us to use the virtual hosting endpoint BUCKETNAME.s3.amazonaws.com).
|
|
*/
|
|
if (strpos($this->endpoint, 'amazonaws.com') !== false)
|
|
{
|
|
$this->setUseLegacyPathStyle(false);
|
|
}
|
|
|
|
} else {
|
|
if (empty($this->getRegion())) {
|
|
$this->setRegion('us-east-1');
|
|
}
|
|
}
|
|
|
|
$this->signatureMethod = $signatureMethod;
|
|
}
|
|
|
|
/**
|
|
* Get the Amazon S3 region
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getRegion(): string
|
|
{
|
|
return $this->region;
|
|
}
|
|
|
|
/**
|
|
* Set the Amazon S3 region
|
|
*
|
|
* @param string $region
|
|
*/
|
|
public function setRegion(string $region): void
|
|
{
|
|
/**
|
|
* You can only leave the region empty if you're using v2 signatures. Anything else gets you an exception.
|
|
*/
|
|
if (empty($region) && ($this->signatureMethod == 'v4'))
|
|
{
|
|
throw new Exception\InvalidRegion;
|
|
}
|
|
|
|
/**
|
|
* Setting a Chinese-looking region force-changes the endpoint but ONLY if you were using the original Amazon S3
|
|
* endpoint. If you're using a custom endpoint and provide a region with 'cn-' in its name we don't override
|
|
* your custom endpoint.
|
|
*/
|
|
if (($this->endpoint == 's3.amazonaws.com') && (substr($region, 0, 3) == 'cn-'))
|
|
{
|
|
$this->setEndpoint('amazonaws.com.cn');
|
|
}
|
|
|
|
$this->region = $region;
|
|
}
|
|
|
|
/**
|
|
* Is the connection to be made over HTTPS?
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function isSSL(): bool
|
|
{
|
|
return $this->useSSL;
|
|
}
|
|
|
|
/**
|
|
* Set the connection SSL preference
|
|
*
|
|
* @param bool $useSSL True to use HTTPS
|
|
*/
|
|
public function setSSL(bool $useSSL): void
|
|
{
|
|
$this->useSSL = $useSSL ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Get the Amazon S3 endpoint
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getEndpoint(): string
|
|
{
|
|
return $this->endpoint;
|
|
}
|
|
|
|
/**
|
|
* Set the Amazon S3 endpoint. Do NOT use a protocol
|
|
*
|
|
* @param string $endpoint Custom endpoint, e.g. 's3.example.com' or 'www.example.com/s3api'
|
|
*/
|
|
public function setEndpoint(string $endpoint): void
|
|
{
|
|
if (stristr($endpoint, '://'))
|
|
{
|
|
throw new Exception\InvalidEndpoint;
|
|
}
|
|
|
|
/**
|
|
* If you set a custom endpoint we have to switch to v2 signatures since our v4 implementation only supports
|
|
* Amazon endpoints.
|
|
*/
|
|
if ((strpos($endpoint, 'amazonaws.com') === false))
|
|
{
|
|
$this->setSignatureMethod('v2');
|
|
}
|
|
|
|
$this->endpoint = $endpoint;
|
|
}
|
|
|
|
/**
|
|
* Should I use legacy, path-style access to the bucket? You should only use it with custom endpoints. Amazon itself
|
|
* is currently deprecating support for path-style access but has extended the migration date to an unknown
|
|
* time https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function getUseLegacyPathStyle(): bool
|
|
{
|
|
return $this->useLegacyPathStyle;
|
|
}
|
|
|
|
/**
|
|
* Set the flag for using legacy, path-style access to the bucket
|
|
*
|
|
* @param bool $useLegacyPathStyle
|
|
*/
|
|
public function setUseLegacyPathStyle(bool $useLegacyPathStyle): void
|
|
{
|
|
$this->useLegacyPathStyle = $useLegacyPathStyle;
|
|
|
|
/**
|
|
* If we are using Amazon S3 proper (not a custom endpoint) we have to set path style access to false.
|
|
* Amazon S3 does not support v2 signatures with path style access at all (it returns an error telling
|
|
* us to use the virtual hosting endpoint BUCKETNAME.s3.amazonaws.com).
|
|
*/
|
|
if ((strpos($this->endpoint, 'amazonaws.com') !== false) && ($this->signatureMethod == 'v2'))
|
|
{
|
|
$this->useLegacyPathStyle = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Should we use the dualstack URL (which will ship traffic over ipv6 in most cases). For more information on these
|
|
* endpoints please read https://docs.aws.amazon.com/AmazonS3/latest/dev/dual-stack-endpoints.html
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function getDualstackUrl(): bool
|
|
{
|
|
return $this->useDualstackUrl;
|
|
}
|
|
|
|
/**
|
|
* Set the flag for using legacy, path-style access to the bucket
|
|
*
|
|
* @param bool $useDualstackUrl
|
|
*/
|
|
public function setUseDualstackUrl(bool $useDualstackUrl): void
|
|
{
|
|
$this->useDualstackUrl = $useDualstackUrl;
|
|
}
|
|
}
|