5 * @package akeebaengine
6 * @copyright Copyright (c)2006-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
7 * @license GNU General Public License version 3, or later
10 namespace Akeeba\Engine\Postproc\Connector\S3v4;
12 // Protection against direct access
13 defined('AKEEBAENGINE') or die();
16 * Holds the Amazon S3 confiugration credentials
25 protected $access = '';
32 protected $secret = '';
35 * Security token. This is only required with temporary credentials provisioned by an EC2 instance.
39 protected $token = '';
42 * Signature calculation method ('v2' or 'v4')
46 protected $signatureMethod = 'v2';
49 * AWS region, used for v4 signatures
53 protected $region = 'us-east-1';
56 * Should I use SSL (HTTPS) to communicate to Amazon S3?
60 protected $useSSL = true;
63 * Should I use SSL (HTTPS) to communicate to Amazon S3?
67 protected $useDualstackUrl = false;
70 * Should I use legacy, path-style access to the bucket? When it's turned off (default) we use virtual hosting style
71 * paths which are RECOMMENDED BY AMAZON per http://docs.aws.amazon.com/AmazonS3/latest/API/APIRest.html
75 protected $useLegacyPathStyle = false;
78 * Amazon S3 endpoint. You can use a custom endpoint with v2 signatures to access third party services which offer
79 * S3 compatibility, e.g. OwnCloud, Google Storage etc.
83 protected $endpoint = 's3.amazonaws.com';
88 * @param string $access Amazon S3 Access Key
89 * @param string $secret Amazon S3 Secret Key
90 * @param string $signatureMethod Signature method (v2 or v4)
91 * @param string $region Region, only required for v4 signatures
93 function __construct(string $access, string $secret, string $signatureMethod = 'v2', string $region = '')
95 $this->setAccess($access);
96 $this->setSecret($secret);
97 $this->setSignatureMethod($signatureMethod);
98 $this->setRegion($region);
102 * Get the Amazon access key
106 public function getAccess(): string
108 return $this->access;
112 * Set the Amazon access key
114 * @param string $access The access key to set
116 * @throws Exception\InvalidAccessKey
118 public function setAccess(string $access): void
122 throw new Exception\InvalidAccessKey;
125 $this->access = $access;
129 * Get the Amazon secret key
133 public function getSecret(): string
135 return $this->secret;
139 * Set the Amazon secret key
141 * @param string $secret The secret key to set
143 * @throws Exception\InvalidSecretKey
145 public function setSecret(string $secret): void
149 throw new Exception\InvalidSecretKey;
152 $this->secret = $secret;
156 * Return the security token. Only for temporary credentials provisioned through an EC2 instance.
160 public function getToken(): string
166 * Set the security token. Only for temporary credentials provisioned through an EC2 instance.
168 * @param string $token
170 public function setToken(string $token): void
172 $this->token = $token;
176 * Get the signature method to use
180 public function getSignatureMethod(): string
182 return $this->signatureMethod;
186 * Set the signature method to use
188 * @param string $signatureMethod One of v2 or v4
190 * @throws Exception\InvalidSignatureMethod
192 public function setSignatureMethod(string $signatureMethod): void
194 $signatureMethod = strtolower($signatureMethod);
195 $signatureMethod = trim($signatureMethod);
197 if (!in_array($signatureMethod, ['v2', 'v4']))
199 throw new Exception\InvalidSignatureMethod;
202 // If you switch to v2 signatures we unset the region.
203 if ($signatureMethod == 'v2')
205 $this->setRegion('');
208 * If we are using Amazon S3 proper (not a custom endpoint) we have to set path style access to false.
209 * Amazon S3 does not support v2 signatures with path style access at all (it returns an error telling
210 * us to use the virtual hosting endpoint BUCKETNAME.s3.amazonaws.com).
212 if (strpos($this->endpoint, 'amazonaws.com') !== false)
214 $this->setUseLegacyPathStyle(false);
218 if (empty($this->getRegion())) {
219 $this->setRegion('us-east-1');
223 $this->signatureMethod = $signatureMethod;
227 * Get the Amazon S3 region
231 public function getRegion(): string
233 return $this->region;
237 * Set the Amazon S3 region
239 * @param string $region
241 public function setRegion(string $region): void
244 * You can only leave the region empty if you're using v2 signatures. Anything else gets you an exception.
246 if (empty($region) && ($this->signatureMethod == 'v4'))
248 throw new Exception\InvalidRegion;
252 * Setting a Chinese-looking region force-changes the endpoint but ONLY if you were using the original Amazon S3
253 * endpoint. If you're using a custom endpoint and provide a region with 'cn-' in its name we don't override
254 * your custom endpoint.
256 if (($this->endpoint == 's3.amazonaws.com') && (substr($region, 0, 3) == 'cn-'))
258 $this->setEndpoint('amazonaws.com.cn');
261 $this->region = $region;
265 * Is the connection to be made over HTTPS?
269 public function isSSL(): bool
271 return $this->useSSL;
275 * Set the connection SSL preference
277 * @param bool $useSSL True to use HTTPS
279 public function setSSL(bool $useSSL): void
281 $this->useSSL = $useSSL ? true : false;
285 * Get the Amazon S3 endpoint
289 public function getEndpoint(): string
291 return $this->endpoint;
295 * Set the Amazon S3 endpoint. Do NOT use a protocol
297 * @param string $endpoint Custom endpoint, e.g. 's3.example.com' or 'www.example.com/s3api'
299 public function setEndpoint(string $endpoint): void
301 if (stristr($endpoint, '://'))
303 throw new Exception\InvalidEndpoint;
307 * If you set a custom endpoint we have to switch to v2 signatures since our v4 implementation only supports
310 if ((strpos($endpoint, 'amazonaws.com') === false))
312 $this->setSignatureMethod('v2');
315 $this->endpoint = $endpoint;
319 * Should I use legacy, path-style access to the bucket? You should only use it with custom endpoints. Amazon itself
320 * is currently deprecating support for path-style access but has extended the migration date to an unknown
321 * time https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/
325 public function getUseLegacyPathStyle(): bool
327 return $this->useLegacyPathStyle;
331 * Set the flag for using legacy, path-style access to the bucket
333 * @param bool $useLegacyPathStyle
335 public function setUseLegacyPathStyle(bool $useLegacyPathStyle): void
337 $this->useLegacyPathStyle = $useLegacyPathStyle;
340 * If we are using Amazon S3 proper (not a custom endpoint) we have to set path style access to false.
341 * Amazon S3 does not support v2 signatures with path style access at all (it returns an error telling
342 * us to use the virtual hosting endpoint BUCKETNAME.s3.amazonaws.com).
344 if ((strpos($this->endpoint, 'amazonaws.com') !== false) && ($this->signatureMethod == 'v2'))
346 $this->useLegacyPathStyle = false;
351 * Should we use the dualstack URL (which will ship traffic over ipv6 in most cases). For more information on these
352 * endpoints please read https://docs.aws.amazon.com/AmazonS3/latest/dev/dual-stack-endpoints.html
356 public function getDualstackUrl(): bool
358 return $this->useDualstackUrl;
362 * Set the flag for using legacy, path-style access to the bucket
364 * @param bool $useDualstackUrl
366 public function setUseDualstackUrl(bool $useDualstackUrl): void
368 $this->useDualstackUrl = $useDualstackUrl;