1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/integration/awskms/aws_kms_client.h"
18
19 #include <cstdlib>
20 #include <fstream>
21 #include <ios>
22 #include <string>
23 #include <vector>
24
25 #include "aws/core/Aws.h"
26 #include "aws/kms/KMSClient.h"
27 #include "gtest/gtest.h"
28 #include "absl/status/status.h"
29 #include "absl/strings/str_cat.h"
30 #include "tink/integration/awskms/internal/test_file_util.h"
31 #include "tink/util/status.h"
32 #include "tink/util/statusor.h"
33 #include "tink/util/test_matchers.h"
34 #include "tink/util/test_util.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace integration {
39 namespace awskms {
40 namespace {
41
42 using ::crypto::tink::integration::awskms::AwsKmsClient;
43 using ::crypto::tink::test::IsOk;
44 using ::crypto::tink::test::IsOkAndHolds;
45 using ::crypto::tink::test::StatusIs;
46 using ::testing::IsNull;
47 using ::testing::IsSubstring;
48 using ::testing::Not;
49
50 constexpr absl::string_view kAwsKey1 =
51 "aws-kms://arn:aws:kms:us-east-1:acc:some/key1";
52 constexpr absl::string_view kAwsKey2 =
53 "aws-kms://arn:aws:kms:us-east-1:acc:some/key2";
54 constexpr absl::string_view kNonAwsKey = "gcp-kms:://some/gcp/key";
55
TEST(AwsKmsClientTest,CreateClientNotBoundToSpecificKeySupportsAllValidKeys)56 TEST(AwsKmsClientTest, CreateClientNotBoundToSpecificKeySupportsAllValidKeys) {
57 std::string creds_file =
58 internal::RunfilesPath("testdata/aws/credentials.ini");
59 util::StatusOr<std::unique_ptr<AwsKmsClient>> client =
60 AwsKmsClient::New(/*key_uri=*/"", creds_file);
61 ASSERT_THAT(client, IsOk());
62 EXPECT_TRUE((*client)->DoesSupport(kAwsKey1));
63 EXPECT_TRUE((*client)->DoesSupport(kAwsKey2));
64 EXPECT_FALSE((*client)->DoesSupport(kNonAwsKey));
65 }
66
67 // Test that a client that is bound to a specific key does not support a
68 // different key URI.
TEST(AwsKmsClientTest,CreateClientBoundToSpecificKeySupportOnlyOneKey)69 TEST(AwsKmsClientTest, CreateClientBoundToSpecificKeySupportOnlyOneKey) {
70 std::string creds_file =
71 internal::RunfilesPath("testdata/aws/credentials.ini");
72 util::StatusOr<std::unique_ptr<AwsKmsClient>> client =
73 AwsKmsClient::New(kAwsKey1, creds_file);
74 ASSERT_THAT(client, IsOk());
75 EXPECT_TRUE((*client)->DoesSupport(kAwsKey1));
76 EXPECT_FALSE((*client)->DoesSupport(kAwsKey2));
77 EXPECT_FALSE((*client)->DoesSupport(kNonAwsKey));
78 }
79
TEST(AwsKmsClientTest,RegisterKmsClient)80 TEST(AwsKmsClientTest, RegisterKmsClient) {
81 std::string creds_file =
82 internal::RunfilesPath("testdata/aws/credentials.ini");
83 ASSERT_THAT(AwsKmsClient::RegisterNewClient(kAwsKey1, creds_file), IsOk());
84 util::StatusOr<const KmsClient*> kms_client = KmsClients::Get(kAwsKey1);
85 EXPECT_THAT(kms_client, IsOkAndHolds(Not(IsNull())));
86 }
87
TEST(AwsKmsClientTest,RegisterKmsClientFailsWhenKeyIsInvalid)88 TEST(AwsKmsClientTest, RegisterKmsClientFailsWhenKeyIsInvalid) {
89 util::Status client = AwsKmsClient::RegisterNewClient(
90 "gcp-kms://projects/someProject/.../cryptoKeys/key1",
91 internal::RunfilesPath("testdata/aws/credentials.ini"));
92 EXPECT_THAT(client, StatusIs(absl::StatusCode::kInvalidArgument));
93 EXPECT_PRED_FORMAT2(IsSubstring, "Invalid key URI",
94 std::string(client.message()));
95 }
96
TEST(AwsKmsClientTest,RegisterKmsClientFailsWhenCredentialsDoNotExist)97 TEST(AwsKmsClientTest, RegisterKmsClientFailsWhenCredentialsDoNotExist) {
98 util::Status client =
99 AwsKmsClient::RegisterNewClient(kAwsKey1, "this/file/does/not/exist.ini");
100 EXPECT_THAT(client, StatusIs(absl::StatusCode::kInvalidArgument));
101 EXPECT_PRED_FORMAT2(IsSubstring, "Error opening file",
102 std::string(client.message()));
103 }
104
TEST(AwsKmsClientTest,RegisterKmsClientFailsWhenMalformedCredentials)105 TEST(AwsKmsClientTest, RegisterKmsClientFailsWhenMalformedCredentials) {
106 // Create an invalid credentials file.
107 std::string malformed_content = "These are malformed credentials.";
108 std::string invalid_credentials_file =
109 internal::RunfilesPath("testdata/aws/invalid.ini");
110 std::ofstream out_stream(invalid_credentials_file, std::ios::binary);
111 out_stream.write(malformed_content.data(), malformed_content.size());
112 out_stream.close();
113
114 util::Status client =
115 AwsKmsClient::RegisterNewClient(kAwsKey1, invalid_credentials_file);
116 EXPECT_THAT(client, StatusIs(absl::StatusCode::kInvalidArgument));
117 EXPECT_PRED_FORMAT2(IsSubstring, "Invalid format",
118 std::string(client.message()));
119 }
120
121 } // namespace
122 } // namespace awskms
123 } // namespace integration
124 } // namespace tink
125 } // namespace crypto
126