123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565 |
- // MinIO C++ Library for Amazon S3 Compatible Cloud Storage
- // Copyright 2022 MinIO, Inc.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #ifndef _MINIO_S3_ARGS_H
- #define _MINIO_S3_ARGS_H
- #include "http.h"
- #include "signer.h"
- #include "sse.h"
- #include "types.h"
- #include <filesystem>
- #include <nlohmann/json.hpp>
- namespace minio {
- namespace s3 {
- struct BaseArgs {
- utils::Multimap extra_headers;
- utils::Multimap extra_query_params;
- }; // struct BaseArgs
- struct BucketArgs : public BaseArgs {
- std::string bucket;
- std::string region;
- error::Error Validate();
- }; // struct BucketArgs
- struct ObjectArgs : public BucketArgs {
- std::string object;
- error::Error Validate();
- }; // struct ObjectArgs
- struct ObjectWriteArgs : public ObjectArgs {
- utils::Multimap headers;
- utils::Multimap user_metadata;
- Sse *sse = NULL;
- std::map<std::string, std::string> tags;
- Retention *retention = NULL;
- bool legal_hold = false;
- utils::Multimap Headers();
- }; // struct ObjectWriteArgs
- struct ObjectVersionArgs : public ObjectArgs {
- std::string version_id;
- }; // struct ObjectVersionArgs
- struct ObjectReadArgs : public ObjectVersionArgs {
- SseCustomerKey *ssec = NULL;
- }; // struct ObjectReadArgs
- struct ObjectConditionalReadArgs : public ObjectReadArgs {
- size_t *offset = NULL;
- size_t *length = NULL;
- std::string match_etag;
- std::string not_match_etag;
- utils::Time modified_since;
- utils::Time unmodified_since;
- utils::Multimap Headers();
- utils::Multimap CopyHeaders();
- }; // struct ObjectConditionalReadArgs
- struct MakeBucketArgs : public BucketArgs {
- bool object_lock = false;
- error::Error Validate();
- }; // struct MakeBucketArgs
- using ListBucketsArgs = BaseArgs;
- using BucketExistsArgs = BucketArgs;
- using RemoveBucketArgs = BucketArgs;
- struct AbortMultipartUploadArgs : public ObjectArgs {
- std::string upload_id;
- error::Error Validate();
- }; // struct AbortMultipartUploadArgs
- struct CompleteMultipartUploadArgs : public ObjectArgs {
- std::string upload_id;
- std::list<Part> parts;
- error::Error Validate();
- }; // struct CompleteMultipartUploadArgs
- struct CreateMultipartUploadArgs : public ObjectArgs {
- utils::Multimap headers;
- }; // struct CreateMultipartUploadArgs
- struct PutObjectBaseArgs : public ObjectWriteArgs {
- long object_size = -1;
- size_t part_size = 0;
- long part_count = 0;
- std::string content_type;
- }; // struct PutObjectBaseArgs
- struct PutObjectApiArgs : public PutObjectBaseArgs {
- std::string_view data;
- utils::Multimap query_params;
- http::ProgressFunction progressfunc = NULL;
- void *progress_userdata = NULL;
- }; // struct PutObjectApiArgs
- struct UploadPartArgs : public ObjectWriteArgs {
- std::string upload_id;
- unsigned int part_number;
- std::string_view data;
- http::ProgressFunction progressfunc = NULL;
- void *progress_userdata = NULL;
- error::Error Validate();
- }; // struct UploadPartArgs
- struct UploadPartCopyArgs : public ObjectWriteArgs {
- std::string upload_id;
- unsigned int part_number;
- utils::Multimap headers;
- error::Error Validate();
- }; // struct UploadPartCopyArgs
- using StatObjectArgs = ObjectConditionalReadArgs;
- using RemoveObjectArgs = ObjectVersionArgs;
- struct DownloadObjectArgs : public ObjectReadArgs {
- std::string filename;
- bool overwrite;
- http::ProgressFunction progressfunc = NULL;
- void *progress_userdata = NULL;
- error::Error Validate();
- }; // struct DownloadObjectArgs
- struct GetObjectArgs : public ObjectConditionalReadArgs {
- http::DataFunction datafunc;
- void *userdata = NULL;
- http::ProgressFunction progressfunc = NULL;
- void *progress_userdata = NULL;
- error::Error Validate();
- }; // struct GetObjectArgs
- struct ListObjectsArgs : public BucketArgs {
- std::string delimiter;
- bool use_url_encoding_type = true;
- std::string marker; // only for ListObjectsV1.
- std::string start_after; // only for ListObjectsV2.
- std::string key_marker; // only for GetObjectVersions.
- unsigned int max_keys = 1000;
- std::string prefix;
- std::string continuation_token; // only for ListObjectsV2.
- bool fetch_owner = false; // only for ListObjectsV2.
- std::string version_id_marker; // only for GetObjectVersions.
- bool include_user_metadata = false; // MinIO extension for ListObjectsV2.
- bool recursive = false;
- bool use_api_v1 = false;
- bool include_versions = false;
- }; // struct ListObjectsArgs
- struct ListObjectsCommonArgs : public BucketArgs {
- std::string delimiter;
- std::string encoding_type;
- unsigned int max_keys = 1000;
- std::string prefix;
- }; // struct ListObjectsCommonArgs
- struct ListObjectsV1Args : public ListObjectsCommonArgs {
- std::string marker;
- ListObjectsV1Args();
- ListObjectsV1Args(ListObjectsArgs args);
- }; // struct ListObjectsV1Args
- struct ListObjectsV2Args : public ListObjectsCommonArgs {
- std::string start_after;
- std::string continuation_token;
- bool fetch_owner;
- bool include_user_metadata;
- ListObjectsV2Args();
- ListObjectsV2Args(ListObjectsArgs args);
- }; // struct ListObjectsV2Args
- struct ListObjectVersionsArgs : public ListObjectsCommonArgs {
- std::string key_marker;
- std::string version_id_marker;
- ListObjectVersionsArgs();
- ListObjectVersionsArgs(ListObjectsArgs args);
- }; // struct ListObjectVersionsArgs
- struct PutObjectArgs : public PutObjectBaseArgs {
- std::istream &stream;
- http::ProgressFunction progressfunc = NULL;
- void *progress_userdata = NULL;
- PutObjectArgs(std::istream &stream, long object_size, long part_size);
- error::Error Validate();
- }; // struct PutObjectArgs
- using CopySource = ObjectConditionalReadArgs;
- struct CopyObjectArgs : public ObjectWriteArgs {
- CopySource source;
- Directive *metadata_directive = NULL;
- Directive *tagging_directive = NULL;
- error::Error Validate();
- }; // struct CopyObjectArgs
- struct ComposeSource : public ObjectConditionalReadArgs {
- error::Error BuildHeaders(size_t object_size, std::string &etag);
- size_t ObjectSize();
- utils::Multimap Headers();
- private:
- long object_size_ = -1;
- utils::Multimap headers_;
- }; // struct ComposeSource
- struct ComposeObjectArgs : public ObjectWriteArgs {
- std::list<ComposeSource> sources;
- error::Error Validate();
- }; // struct ComposeObjectArgs
- struct UploadObjectArgs : public PutObjectBaseArgs {
- std::string filename;
- http::ProgressFunction progressfunc = NULL;
- void *progress_userdata = NULL;
- error::Error Validate();
- }; // struct UploadObjectArgs
- struct RemoveObjectsApiArgs : public BucketArgs {
- bool bypass_governance_mode = false;
- bool quiet = true;
- std::list<DeleteObject> objects;
- }; // struct RemoveObjectsApiArgs
- using DeleteObjectFunction = std::function<bool(DeleteObject &)>;
- struct RemoveObjectsArgs : public BucketArgs {
- bool bypass_governance_mode = false;
- DeleteObjectFunction func = NULL;
- error::Error Validate();
- }; // struct RemoveObjectsArgs
- struct SelectObjectContentArgs : public ObjectReadArgs {
- SelectRequest &request;
- SelectResultFunction resultfunc = NULL;
- SelectObjectContentArgs(SelectRequest &req, SelectResultFunction func)
- : request(req), resultfunc(func) {}
- error::Error Validate();
- }; // struct SelectObjectContentArgs
- struct ListenBucketNotificationArgs : public BucketArgs {
- std::string prefix;
- std::string suffix;
- std::list<std::string> events;
- NotificationRecordsFunction func = NULL;
- error::Error Validate();
- }; // struct ListenBucketNotificationArgs
- using DeleteBucketPolicyArgs = BucketArgs;
- using GetBucketPolicyArgs = BucketArgs;
- struct SetBucketPolicyArgs : public BucketArgs {
- std::string policy;
- error::Error Validate();
- }; // struct SetBucketPolicy
- using DeleteBucketNotificationArgs = BucketArgs;
- using GetBucketNotificationArgs = BucketArgs;
- struct SetBucketNotificationArgs : public BucketArgs {
- NotificationConfig &config;
- SetBucketNotificationArgs(NotificationConfig &configvalue)
- : config(configvalue) {}
- }; // struct SetBucketNotification
- using DeleteBucketEncryptionArgs = BucketArgs;
- using GetBucketEncryptionArgs = BucketArgs;
- struct SetBucketEncryptionArgs : public BucketArgs {
- SseConfig &config;
- SetBucketEncryptionArgs(SseConfig &sseconfig) : config(sseconfig) {}
- error::Error Validate();
- }; // struct SetBucketEncryption
- using GetBucketVersioningArgs = BucketArgs;
- struct SetBucketVersioningArgs : public BucketArgs {
- Boolean status;
- Boolean mfa_delete;
- error::Error Validate();
- }; // struct SetBucketVersioning
- using DeleteBucketReplicationArgs = BucketArgs;
- using GetBucketReplicationArgs = BucketArgs;
- struct SetBucketReplicationArgs : public BucketArgs {
- ReplicationConfig &config;
- SetBucketReplicationArgs(ReplicationConfig &value) : config(value) {}
- }; // struct SetBucketReplication
- using DeleteBucketLifecycleArgs = BucketArgs;
- using GetBucketLifecycleArgs = BucketArgs;
- struct SetBucketLifecycleArgs : public BucketArgs {
- LifecycleConfig &config;
- SetBucketLifecycleArgs(LifecycleConfig &value) : config(value) {}
- }; // struct SetBucketLifecycle
- using DeleteBucketTagsArgs = BucketArgs;
- using GetBucketTagsArgs = BucketArgs;
- struct SetBucketTagsArgs : public BucketArgs {
- std::map<std::string, std::string> tags;
- error::Error Validate();
- }; // struct SetBucketTags
- using DeleteObjectLockConfigArgs = BucketArgs;
- using GetObjectLockConfigArgs = BucketArgs;
- struct SetObjectLockConfigArgs : public BucketArgs {
- ObjectLockConfig config;
- error::Error Validate();
- }; // struct SetObjectLockConfig
- using DeleteObjectTagsArgs = ObjectVersionArgs;
- using GetObjectTagsArgs = ObjectVersionArgs;
- struct SetObjectTagsArgs : public ObjectVersionArgs {
- std::map<std::string, std::string> tags;
- error::Error Validate();
- }; // struct SetObjectTags
- using EnableObjectLegalHoldArgs = ObjectVersionArgs;
- using DisableObjectLegalHoldArgs = ObjectVersionArgs;
- using IsObjectLegalHoldEnabledArgs = ObjectVersionArgs;
- using GetObjectRetentionArgs = ObjectVersionArgs;
- struct SetObjectRetentionArgs : public ObjectVersionArgs {
- RetentionMode retention_mode;
- utils::Time retain_until_date;
- error::Error Validate();
- }; // struct SetObjectRetention
- inline constexpr unsigned int kDefaultExpirySeconds =
- (60 * 60 * 24 * 7); // 7 days
- struct GetPresignedObjectUrlArgs : public ObjectVersionArgs {
- http::Method method;
- unsigned int expiry_seconds = kDefaultExpirySeconds;
- utils::Time request_time;
- error::Error Validate();
- }; // struct GetPresignedObjectUrlArgs
- struct PostPolicy {
- std::string bucket;
- std::string region;
- PostPolicy(std::string bucket, utils::Time expiration) {
- this->bucket = bucket;
- this->expiration_ = expiration;
- }
- operator bool() const { return !bucket.empty() && !expiration_; }
- error::Error AddEqualsCondition(std::string element, std::string value) {
- if (element.empty()) {
- return error::Error("condition element cannot be empty");
- }
- element = trimDollar(element);
- if (element == "success_action_redirect" || element == "redirect" ||
- element == "content-length-range") {
- return error::Error(element + " is unsupported for equals condition");
- }
- if (isReservedElement(element)) {
- return error::Error(element + " cannot be set");
- }
- conditions_[eq_][element] = value;
- return error::SUCCESS;
- }
- error::Error RemoveEqualsCondition(std::string element) {
- if (element.empty()) {
- return error::Error("condition element cannot be empty");
- }
- conditions_[eq_].erase(element);
- return error::SUCCESS;
- }
- error::Error AddStartsWithCondition(std::string element, std::string value) {
- if (element.empty()) {
- return error::Error("condition element cannot be empty");
- }
- element = trimDollar(element);
- if (element == "success_action_status" ||
- element == "content-length-range" ||
- (utils::StartsWith(element, "x-amz-") &&
- utils::StartsWith(element, "x-amz-meta-"))) {
- return error::Error(element +
- " is unsupported for starts-with condition");
- }
- if (isReservedElement(element)) {
- return error::Error(element + " cannot be set");
- }
- conditions_[starts_with_][element] = value;
- return error::SUCCESS;
- }
- error::Error RemoveStartsWithCondition(std::string element) {
- if (element.empty()) {
- return error::Error("condition element cannot be empty");
- }
- conditions_[starts_with_].erase(element);
- return error::SUCCESS;
- }
- error::Error AddContentLengthRangeCondition(size_t lower_limit,
- size_t upper_limit) {
- if (lower_limit > upper_limit) {
- return error::Error("lower limit cannot be greater than upper limit");
- }
- lower_limit_ = Integer(lower_limit);
- upper_limit_ = Integer(upper_limit);
- return error::SUCCESS;
- }
- void RemoveContentLengthRangeCondition() {
- lower_limit_ = Integer();
- upper_limit_ = Integer();
- }
- error::Error FormData(std::map<std::string, std::string> &data,
- std::string access_key, std::string secret_key,
- std::string session_token, std::string region) {
- if (region.empty()) return error::Error("region cannot be empty");
- if (conditions_[eq_]["key"].empty() &&
- conditions_[starts_with_]["key"].empty()) {
- return error::Error("key condition must be set");
- }
- nlohmann::json policy;
- policy["expiration"] = expiration_.ToISO8601UTC();
- nlohmann::json conditions = nlohmann::json::array();
- conditions.push_back({eq_, "$bucket", bucket});
- for (auto &[cond_key, cond] : conditions_) {
- for (auto &[key, value] : cond) {
- conditions.push_back({cond_key, "$" + key, value});
- }
- }
- if (lower_limit_ && upper_limit_) {
- conditions.push_back(
- {"content-length-range", lower_limit_.Get(), upper_limit_.Get()});
- }
- utils::Time date = utils::Time::Now();
- std::string credential = getCredentialString(access_key, date, region);
- std::string amz_date = date.ToAmzDate();
- conditions.push_back({eq_, "$x-amz-algorithm", algorithm_});
- conditions.push_back({eq_, "$x-amz-credential", credential});
- if (!session_token.empty()) {
- conditions.push_back({eq_, "$x-amz-security-token", session_token});
- }
- conditions.push_back({eq_, "$x-amz-date", amz_date});
- policy["conditions"] = conditions;
- std::string encoded_policy = utils::Base64Encode(policy.dump());
- std::string signature =
- signer::PostPresignV4(encoded_policy, secret_key, date, region);
- data["x-amz-algorithm"] = algorithm_;
- data["x-amz-credential"] = credential;
- data["x-amz-date"] = amz_date;
- data["policy"] = encoded_policy;
- data["x-amz-signature"] = signature;
- if (!session_token.empty()) {
- data["x-amz-security-token"] = session_token;
- }
- return error::SUCCESS;
- }
- private:
- static constexpr const char *eq_ = "eq";
- static constexpr const char *starts_with_ = "starts-with";
- static constexpr const char *algorithm_ = "AWS4-HMAC-SHA256";
- utils::Time expiration_;
- std::map<std::string, std::map<std::string, std::string>> conditions_;
- Integer lower_limit_;
- Integer upper_limit_;
- static std::string trimDollar(std::string value) {
- if (value.front() == '$') value.erase(0, 1);
- return value;
- }
- static std::string getCredentialString(std::string access_key,
- utils::Time date, std::string region) {
- return access_key + "/" + date.ToSignerDate() + "/" + region +
- "/s3/aws4_request";
- }
- static bool isReservedElement(std::string element) {
- return element == "bucket" || element == "x-amz-algorithm" ||
- element == "x-amz-credential" || element == "x-amz-date" ||
- element == "policy" || element == "x-amz-signature";
- }
- }; // struct PostPolicy
- } // namespace s3
- } // namespace minio
- #endif // #ifndef __MINIO_S3_ARGS_H
|