Welcome to mirror list, hosted at ThFree Co, Russian Federation.

S3EncryptionMultipartUploader.php « Crypto « S3 « src « aws-sdk-php « aws - github.com/nextcloud/3rdparty.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: ddf1d2df99b6b6c5144fb3c2abb1691193c34c5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<?php
namespace Aws\S3\Crypto;

use Aws\Crypto\AbstractCryptoClient;
use Aws\Crypto\EncryptionTrait;
use Aws\Crypto\MetadataEnvelope;
use Aws\Crypto\Cipher\CipherBuilderTrait;
use Aws\S3\MultipartUploader;
use Aws\S3\S3ClientInterface;
use GuzzleHttp\Promise;

/**
 * Encapsulates the execution of a multipart upload of an encrypted object to S3.
 *
 * Legacy implementation using older encryption workflow. Use
 * S3EncryptionMultipartUploaderV2 if possible.
 *
 * @deprecated
 */
class S3EncryptionMultipartUploader extends MultipartUploader
{
    use CipherBuilderTrait;
    use CryptoParamsTrait;
    use EncryptionTrait;
    use UserAgentTrait;

    const CRYPTO_VERSION = '1n';

    /**
     * Returns if the passed cipher name is supported for encryption by the SDK.
     *
     * @param string $cipherName The name of a cipher to verify is registered.
     *
     * @return bool If the cipher passed is in our supported list.
     */
    public static function isSupportedCipher($cipherName)
    {
        return in_array($cipherName, AbstractCryptoClient::$supportedCiphers);
    }

    private $provider;
    private $instructionFileSuffix;
    private $strategy;

    /**
     * Creates a multipart upload for an S3 object after encrypting it.
     *
     * The required configuration options are as follows:
     *
     * - @MaterialsProvider: (MaterialsProvider) Provides Cek, Iv, and Cek
     *   encrypting/decrypting for encryption metadata.
     * - @CipherOptions: (array) Cipher options for encrypting data. A Cipher
     *   is required. Accepts the following options:
     *       - Cipher: (string) cbc|gcm
     *            See also: AbstractCryptoClient::$supportedCiphers. Note that
     *            cbc is deprecated and gcm should be used when possible.
     *       - KeySize: (int) 128|192|256
     *            See also: MaterialsProvider::$supportedKeySizes
     *       - Aad: (string) Additional authentication data. This option is
     *            passed directly to OpenSSL when using gcm. It is ignored when
     *            using cbc.
     * - bucket: (string) Name of the bucket to which the object is
     *   being uploaded.
     * - key: (string) Key to use for the object being uploaded.
     *
     * The optional configuration arguments are as follows:
     *
     * - @MetadataStrategy: (MetadataStrategy|string|null) Strategy for storing
     *   MetadataEnvelope information. Defaults to using a
     *   HeadersMetadataStrategy. Can either be a class implementing
     *   MetadataStrategy, a class name of a predefined strategy, or empty/null
     *   to default.
     * - @InstructionFileSuffix: (string|null) Suffix used when writing to an
     *   instruction file if an using an InstructionFileMetadataHandler was
     *   determined.
     * - acl: (string) ACL to set on the object being upload. Objects are
     *   private by default.
     * - before_complete: (callable) Callback to invoke before the
     *   `CompleteMultipartUpload` operation. The callback should have a
     *   function signature like `function (Aws\Command $command) {...}`.
     * - before_initiate: (callable) Callback to invoke before the
     *   `CreateMultipartUpload` operation. The callback should have a function
     *   signature like `function (Aws\Command $command) {...}`.
     * - before_upload: (callable) Callback to invoke before any `UploadPart`
     *   operations. The callback should have a function signature like
     *   `function (Aws\Command $command) {...}`.
     * - concurrency: (int, default=int(5)) Maximum number of concurrent
     *   `UploadPart` operations allowed during the multipart upload.
     * - params: (array) An array of key/value parameters that will be applied
     *   to each of the sub-commands run by the uploader as a base.
     *   Auto-calculated options will override these parameters. If you need
     *   more granularity over parameters to each sub-command, use the before_*
     *   options detailed above to update the commands directly.
     * - part_size: (int, default=int(5242880)) Part size, in bytes, to use when
     *   doing a multipart upload. This must between 5 MB and 5 GB, inclusive.
     * - state: (Aws\Multipart\UploadState) An object that represents the state
     *   of the multipart upload and that is used to resume a previous upload.
     *   When this option is provided, the `bucket`, `key`, and `part_size`
     *   options are ignored.
     *
     * @param S3ClientInterface $client Client used for the upload.
     * @param mixed             $source Source of the data to upload.
     * @param array             $config Configuration used to perform the upload.
     */
    public function __construct(
        S3ClientInterface $client,
        $source,
        array $config = []
    ) {
        $this->appendUserAgent($client, 'feat/s3-encrypt/' . self::CRYPTO_VERSION);
        $this->client = $client;
        $config['params'] = [];
        if (!empty($config['bucket'])) {
            $config['params']['Bucket'] = $config['bucket'];
        }
        if (!empty($config['key'])) {
            $config['params']['Key'] = $config['key'];
        }

        $this->provider = $this->getMaterialsProvider($config);
        unset($config['@MaterialsProvider']);

        $this->instructionFileSuffix = $this->getInstructionFileSuffix($config);
        unset($config['@InstructionFileSuffix']);
        $this->strategy = $this->getMetadataStrategy(
            $config,
            $this->instructionFileSuffix
        );
        if ($this->strategy === null) {
            $this->strategy = self::getDefaultStrategy();
        }
        unset($config['@MetadataStrategy']);

        $config['prepare_data_source'] = $this->getEncryptingDataPreparer();

        parent::__construct($client, $source, $config);
    }

    private static function getDefaultStrategy()
    {
        return new HeadersMetadataStrategy();
    }

    private function getEncryptingDataPreparer()
    {
        return function() {
            // Defer encryption work until promise is executed
            $envelope = new MetadataEnvelope();

            list($this->source, $params) = Promise\Create::promiseFor($this->encrypt(
                $this->source,
                $this->config['@cipheroptions'] ?: [],
                $this->provider,
                $envelope
            ))->then(
                function ($bodyStream) use ($envelope) {
                    $params = $this->strategy->save(
                        $envelope,
                        $this->config['params']
                    );
                    return [$bodyStream, $params];
                }
            )->wait();

            $this->source->rewind();
            $this->config['params'] = $params;
        };
    }
}