@@ -51,6 +51,7 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
51
51
// https://docs.aws.amazon.com/AmazonS3/latest/userguide/specifying-kms-encryption.html#sse-request-headers-kms
52
52
bool use_sse_kms = auth_params.kms_key_id .length () > 0 && (method == " POST" || method == " PUT" ) &&
53
53
query.find (" uploadId" ) == std::string::npos;
54
+ bool use_sse_c = auth_params.sse_c_key .length () > 0 && auth_params.sse_c_key_md5 .length () > 0 ;
54
55
55
56
res[" x-amz-date" ] = datetime_now;
56
57
res[" x-amz-content-sha256" ] = payload_hash;
@@ -61,6 +62,11 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
61
62
res[" x-amz-server-side-encryption" ] = " aws:kms" ;
62
63
res[" x-amz-server-side-encryption-aws-kms-key-id" ] = auth_params.kms_key_id ;
63
64
}
65
+ if (use_sse_c) {
66
+ res[" x-amz-server-side-encryption-customer-algorithm" ] = " AES256" ;
67
+ res[" x-amz-server-side-encryption-customer-key" ] = auth_params.sse_c_key ;
68
+ res[" x-amz-server-side-encryption-customer-key-md5" ] = auth_params.sse_c_key_md5 ;
69
+ }
64
70
65
71
string signed_headers = " " ;
66
72
hash_bytes canonical_request_hash;
@@ -75,6 +81,9 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
75
81
if (use_sse_kms) {
76
82
signed_headers += " ;x-amz-server-side-encryption;x-amz-server-side-encryption-aws-kms-key-id" ;
77
83
}
84
+ if (use_sse_c) {
85
+ signed_headers += " ;x-amz-server-side-encryption-customer-algorithm;x-amz-server-side-encryption-customer-key;x-amz-server-side-encryption-customer-key-md5" ;
86
+ }
78
87
auto canonical_request = method + " \n " + S3FileSystem::UrlEncode (url) + " \n " + query;
79
88
if (content_type.length () > 0 ) {
80
89
canonical_request += " \n content-type:" + content_type;
@@ -87,6 +96,11 @@ static HTTPHeaders create_s3_header(string url, string query, string host, strin
87
96
canonical_request += " \n x-amz-server-side-encryption:aws:kms" ;
88
97
canonical_request += " \n x-amz-server-side-encryption-aws-kms-key-id:" + auth_params.kms_key_id ;
89
98
}
99
+ if (use_sse_c) {
100
+ canonical_request += " \n x-amz-server-side-encryption-customer-algorithm:AES256" ;
101
+ canonical_request += " \n x-amz-server-side-encryption-customer-key:" + auth_params.sse_c_key ;
102
+ canonical_request += " \n x-amz-server-side-encryption-customer-key-md5:" + auth_params.sse_c_key_md5 ;
103
+ }
90
104
91
105
canonical_request += " \n\n " + signed_headers + " \n " + payload_hash;
92
106
sha256 (canonical_request.c_str (), canonical_request.length (), canonical_request_hash);
@@ -143,6 +157,8 @@ void AWSEnvironmentCredentialsProvider::SetAll() {
143
157
this ->SetExtensionOptionValue (" s3_endpoint" , DUCKDB_ENDPOINT_ENV_VAR);
144
158
this ->SetExtensionOptionValue (" s3_use_ssl" , DUCKDB_USE_SSL_ENV_VAR);
145
159
this ->SetExtensionOptionValue (" s3_kms_key_id" , DUCKDB_KMS_KEY_ID_ENV_VAR);
160
+ this ->SetExtensionOptionValue (" s3_sse_c_key" , DUCKDB_SSE_C_KEY_ENV_VAR);
161
+ this ->SetExtensionOptionValue (" s3_sse_c_key_md5" , DUCKDB_SSE_C_KEY_MD5_ENV_VAR);
146
162
}
147
163
148
164
S3AuthParams AWSEnvironmentCredentialsProvider::CreateParams () {
@@ -155,6 +171,8 @@ S3AuthParams AWSEnvironmentCredentialsProvider::CreateParams() {
155
171
params.session_token = SESSION_TOKEN_ENV_VAR;
156
172
params.endpoint = DUCKDB_ENDPOINT_ENV_VAR;
157
173
params.kms_key_id = DUCKDB_KMS_KEY_ID_ENV_VAR;
174
+ params.sse_c_key = DUCKDB_SSE_C_KEY_ENV_VAR;
175
+ params.sse_c_key_md5 = DUCKDB_SSE_C_KEY_MD5_ENV_VAR;
158
176
params.use_ssl = DUCKDB_USE_SSL_ENV_VAR;
159
177
160
178
return params;
@@ -179,6 +197,8 @@ S3AuthParams S3AuthParams::ReadFrom(optional_ptr<FileOpener> opener, FileOpenerI
179
197
secret_reader.TryGetSecretKeyOrSetting (" region" , " s3_region" , result.region );
180
198
secret_reader.TryGetSecretKeyOrSetting (" use_ssl" , " s3_use_ssl" , result.use_ssl );
181
199
secret_reader.TryGetSecretKeyOrSetting (" kms_key_id" , " s3_kms_key_id" , result.kms_key_id );
200
+ secret_reader.TryGetSecretKeyOrSetting (" sse_c_key" , " s3_sse_c_key" , result.sse_c_key );
201
+ secret_reader.TryGetSecretKeyOrSetting (" sse_c_key_md5" , " s3_sse_c_key_md5" , result.sse_c_key_md5 );
182
202
secret_reader.TryGetSecretKeyOrSetting (" s3_url_compatibility_mode" , " s3_url_compatibility_mode" ,
183
203
result.s3_url_compatibility_mode );
184
204
@@ -216,6 +236,8 @@ unique_ptr<KeyValueSecret> CreateSecret(vector<string> &prefix_paths_p, string &
216
236
return_value->secret_map [" url_style" ] = params.url_style ;
217
237
return_value->secret_map [" use_ssl" ] = params.use_ssl ;
218
238
return_value->secret_map [" kms_key_id" ] = params.kms_key_id ;
239
+ return_value->secret_map [" sse_c_key" ] = params.sse_c_key ;
240
+ return_value->secret_map [" sse_c_key_md5" ] = params.sse_c_key_md5 ;
219
241
return_value->secret_map [" s3_url_compatibility_mode" ] = params.s3_url_compatibility_mode ;
220
242
221
243
// ! Set redact keys
0 commit comments