/root/doris/cloud/src/common/kms.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #include "common/kms.h" |
19 | | |
20 | | #include <alibabacloud/core/AlibabaCloud.h> |
21 | | #include <alibabacloud/core/CommonClient.h> |
22 | | #include <json/json.h> |
23 | | |
24 | | #include <memory> |
25 | | |
26 | | #include "common/logging.h" |
27 | | #include "cpp/sync_point.h" |
28 | | namespace doris::cloud { |
29 | | |
30 | 8 | int create_kms_client(KmsConf&& conf, std::unique_ptr<KmsClient>* kms_client) { |
31 | 8 | if (conf.ak.empty() || conf.sk.empty() || conf.endpoint.empty() || conf.region.empty() || |
32 | 8 | conf.provider.empty() || conf.cmk.empty()) { |
33 | 0 | LOG(WARNING) << "incorrect kms conf"; |
34 | 0 | return -1; |
35 | 0 | } |
36 | | // Todo: only support ali cloud now |
37 | 8 | if (conf.provider != "ali") { |
38 | 1 | LOG(WARNING) << "only support kms for ali cloud now"; |
39 | 1 | return -1; |
40 | 1 | } |
41 | 7 | *kms_client = std::make_unique<AliKmsClient>(std::move(conf)); |
42 | 7 | return 0; |
43 | 8 | } |
44 | | |
45 | 7 | AliKmsClient::AliKmsClient(KmsConf&& conf) : KmsClient(std::move(conf)) { |
46 | 7 | AlibabaCloud::InitializeSdk(); |
47 | 7 | } |
48 | | |
49 | 7 | AliKmsClient::~AliKmsClient() { |
50 | 7 | AlibabaCloud::ShutdownSdk(); |
51 | 7 | } |
52 | | |
53 | 7 | int AliKmsClient::init() { |
54 | 7 | AlibabaCloud::ClientConfiguration configuration(conf_.region); |
55 | 7 | AlibabaCloud::Credentials credential(conf_.ak, conf_.sk); |
56 | 7 | kms_client_ = std::make_unique<AlibabaCloud::CommonClient>(std::move(credential), |
57 | 7 | std::move(configuration)); |
58 | 7 | return 0; |
59 | 7 | } |
60 | | |
61 | 0 | int AliKmsClient::encrypt(const std::string& plaintext, std::string* output) { |
62 | 0 | AlibabaCloud::CommonRequest request(AlibabaCloud::CommonRequest::RequestPattern::RpcPattern); |
63 | 0 | request.setHttpMethod(AlibabaCloud::HttpRequest::Method::Post); |
64 | 0 | request.setDomain(conf_.endpoint); |
65 | 0 | request.setVersion("2016-01-20"); |
66 | 0 | request.setQueryParameter("Action", "Encrypt"); |
67 | 0 | request.setQueryParameter("KeyId", conf_.cmk); |
68 | 0 | request.setQueryParameter("Plaintext", plaintext); |
69 | |
|
70 | 0 | auto response = kms_client_->commonResponse(request); |
71 | 0 | if (response.isSuccess()) { |
72 | 0 | Json::Value json; |
73 | 0 | Json::Reader reader; |
74 | 0 | if (reader.parse(response.result().payload(), json) && json.isMember("CiphertextBlob")) { |
75 | 0 | *output = json["CiphertextBlob"].asString(); |
76 | 0 | return 0; |
77 | 0 | } else { |
78 | 0 | LOG(WARNING) << "failed to parse response, response=" << response.result().payload(); |
79 | 0 | return -1; |
80 | 0 | } |
81 | 0 | } else { |
82 | 0 | LOG(WARNING) << "failed to encrypt data, error=" << response.error().errorMessage() |
83 | 0 | << " request id=" << response.error().requestId(); |
84 | 0 | return -1; |
85 | 0 | } |
86 | 0 | return 0; |
87 | 0 | } |
88 | | |
89 | 3 | int AliKmsClient::decrypt(const std::string& ciphertext, std::string* output) { |
90 | 3 | TEST_SYNC_POINT_RETURN_WITH_VALUE("alikms::decrypt", (int)0, output); |
91 | 0 | AlibabaCloud::CommonRequest request(AlibabaCloud::CommonRequest::RequestPattern::RpcPattern); |
92 | 0 | request.setHttpMethod(AlibabaCloud::HttpRequest::Method::Post); |
93 | 0 | request.setDomain(conf_.endpoint); |
94 | 0 | request.setVersion("2016-01-20"); |
95 | 0 | request.setQueryParameter("Action", "Decrypt"); |
96 | 0 | request.setQueryParameter("CiphertextBlob", ciphertext); |
97 | |
|
98 | 0 | auto response = kms_client_->commonResponse(request); |
99 | 0 | if (response.isSuccess()) { |
100 | 0 | Json::Value json; |
101 | 0 | Json::Reader reader; |
102 | 0 | if (reader.parse(response.result().payload(), json) && json.isMember("Plaintext")) { |
103 | 0 | *output = json["Plaintext"].asString(); |
104 | 0 | return 0; |
105 | 0 | } else { |
106 | 0 | LOG(WARNING) << "failed to parse response, response=" << response.result().payload(); |
107 | 0 | return -1; |
108 | 0 | } |
109 | 0 | } else { |
110 | 0 | LOG(WARNING) << "failed to decrypt data, error=" << response.error().errorMessage() |
111 | 0 | << " request id=" << response.error().requestId(); |
112 | 0 | return -1; |
113 | 0 | } |
114 | 0 | return 0; |
115 | 0 | } |
116 | | |
117 | 3 | int AliKmsClient::generate_data_key(std::string* ciphertext, std::string* plaintext) { |
118 | 3 | TEST_SYNC_POINT_RETURN_WITH_VALUE("alikms::generate_data_key", (int)0, ciphertext, plaintext); |
119 | 0 | AlibabaCloud::CommonRequest request(AlibabaCloud::CommonRequest::RequestPattern::RpcPattern); |
120 | 0 | request.setHttpMethod(AlibabaCloud::HttpRequest::Method::Post); |
121 | 0 | request.setDomain(conf_.endpoint); |
122 | 0 | request.setVersion("2016-01-20"); |
123 | 0 | request.setQueryParameter("Action", "GenerateDataKey"); |
124 | 0 | request.setQueryParameter("KeySpec", "AES_256"); |
125 | 0 | request.setQueryParameter("KeyId", "839ff82c-dcb5-4438-a6a4-6ec832443ba8"); |
126 | |
|
127 | 0 | auto response = kms_client_->commonResponse(request); |
128 | 0 | if (response.isSuccess()) { |
129 | 0 | Json::Value json; |
130 | 0 | Json::Reader reader; |
131 | 0 | if (reader.parse(response.result().payload(), json) && json.isMember("Plaintext") && |
132 | 0 | json.isMember("CiphertextBlob")) { |
133 | 0 | *plaintext = json["Plaintext"].asString(); |
134 | 0 | *ciphertext = json["CiphertextBlob"].asString(); |
135 | 0 | return 0; |
136 | 0 | } else { |
137 | 0 | LOG(WARNING) << "failed to parse response, response=" << response.result().payload(); |
138 | 0 | return -1; |
139 | 0 | } |
140 | 0 | } else { |
141 | 0 | LOG(WARNING) << "failed to generate data key, error=" << response.error().errorMessage() |
142 | 0 | << " request id=" << response.error().requestId(); |
143 | 0 | return -1; |
144 | 0 | } |
145 | 0 | return 0; |
146 | 0 | } |
147 | | |
148 | | } // namespace doris::cloud |