1 // Copyright 2022 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 #include "tink/internal/monitoring_util.h"
17
18 #include <stdint.h>
19
20 #include <memory>
21 #include <string>
22 #include <utility>
23 #include <vector>
24
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "absl/container/flat_hash_map.h"
28 #include "absl/memory/memory.h"
29 #include "absl/status/status.h"
30 #include "absl/strings/string_view.h"
31 #include "tink/key_status.h"
32 #include "tink/monitoring/monitoring.h"
33 #include "tink/primitive_set.h"
34 #include "tink/util/status.h"
35 #include "tink/util/statusor.h"
36 #include "tink/util/test_matchers.h"
37 #include "proto/tink.pb.h"
38
39 namespace crypto {
40 namespace tink {
41 namespace internal {
42 namespace {
43
44 using ::crypto::tink::MonitoringKeySetInfo;
45 using ::crypto::tink::test::IsOk;
46 using ::google::crypto::tink::KeysetInfo;
47 using ::google::crypto::tink::KeyStatusType;
48 using ::google::crypto::tink::OutputPrefixType;
49 using ::testing::UnorderedElementsAre;
50 using ::testing::UnorderedElementsAreArray;
51
TEST(MonitoringUtilTest,MonitoringKeySetInfoFromPrimitiveSetEmptyPrimitiveSet)52 TEST(MonitoringUtilTest,
53 MonitoringKeySetInfoFromPrimitiveSetEmptyPrimitiveSet) {
54 PrimitiveSet<std::string> primitive_set;
55 EXPECT_THAT(MonitoringKeySetInfoFromPrimitiveSet(primitive_set).status(),
56 test::StatusIs(absl::StatusCode::kInvalidArgument));
57 }
58
TEST(MonitoringUtilTest,MonitoringKeySetInfoFromPrimitiveSetNullPrimary)59 TEST(MonitoringUtilTest, MonitoringKeySetInfoFromPrimitiveSetNullPrimary) {
60 PrimitiveSet<std::string> primitive_set;
61 auto some_string = absl::make_unique<std::string>("Text");
62 KeysetInfo::KeyInfo key_info;
63 key_info.set_type_url(
64 "type.googleapis.com/google.crypto.tink.SomePrimitiveInstance");
65 key_info.set_status(KeyStatusType::ENABLED);
66 key_info.set_key_id(1);
67 key_info.set_output_prefix_type(OutputPrefixType::TINK);
68 util::StatusOr<PrimitiveSet<std::string>::Entry<std::string> *> added_entry =
69 primitive_set.AddPrimitive(std::move(some_string), key_info);
70 ASSERT_THAT(added_entry, IsOk());
71 EXPECT_THAT(MonitoringKeySetInfoFromPrimitiveSet(primitive_set).status(),
72 test::StatusIs(absl::StatusCode::kInvalidArgument));
73 }
74
75 // Utility struct to hold primitive and key info.
76 template <class P>
77 struct PrimitiveSetInputPrimitive {
78 std::unique_ptr<P> primitive;
79 KeysetInfo::KeyInfo key_info;
80 };
81
NewPrimitiveSetInputPrimitive(absl::string_view primitive_value,absl::string_view type_url,KeyStatusType status,uint32_t key_id,OutputPrefixType prefix_type)82 PrimitiveSetInputPrimitive<std::string> NewPrimitiveSetInputPrimitive(
83 absl::string_view primitive_value, absl::string_view type_url,
84 KeyStatusType status, uint32_t key_id, OutputPrefixType prefix_type) {
85 auto some_string = absl::make_unique<std::string>(primitive_value);
86 KeysetInfo::KeyInfo key_info;
87 std::string type_url_str(type_url);
88 key_info.set_type_url(type_url_str);
89 key_info.set_status(status);
90 key_info.set_key_id(key_id);
91 key_info.set_output_prefix_type(prefix_type);
92 return {/*primitive=*/std::move(some_string),
93 /*key_info=*/std::move(key_info)};
94 }
95
96 MATCHER_P(MonitoringKeySetInfoEntryEq, other, "") {
97 return arg.GetStatus() == other.GetStatus() &&
98 arg.GetKeyId() == other.GetKeyId() &&
99 arg.GetKeyPrefix() == other.GetKeyPrefix() &&
100 arg.GetKeyType() == other.GetKeyType();
101 }
102
TEST(MonitoringUtilTest,MonitoringKeySetInfoFromPrimitiveSetValid)103 TEST(MonitoringUtilTest, MonitoringKeySetInfoFromPrimitiveSetValid) {
104 const absl::flat_hash_map<std::string, std::string> kAnnotations = {
105 {"key1", "value1"},
106 {"key2", "value2"},
107 };
108 PrimitiveSet<std::string> primitive_set(kAnnotations);
109
110 constexpr absl::string_view kPrimitive1KeyTyepUrl =
111 "type.googleapis.com/google.crypto.tink.SomePrimitiveInstance";
112 constexpr absl::string_view kPrimitive2KeyTypeUrl =
113 "type.googleapis.com/google.crypto.tink.SomeOtherPrimitiveInstance";
114
115 PrimitiveSetInputPrimitive<std::string> primitive_1 =
116 NewPrimitiveSetInputPrimitive(
117 /*primitive_value=*/"primitive_1", kPrimitive1KeyTyepUrl,
118 /*status=*/KeyStatusType::ENABLED, /*key_id=*/1,
119 /*prefix_type=*/OutputPrefixType::TINK);
120
121 PrimitiveSetInputPrimitive<std::string> primitive_2 =
122 NewPrimitiveSetInputPrimitive(
123 /*primitive_value=*/"primitive_2", kPrimitive2KeyTypeUrl,
124 /*status=*/KeyStatusType::ENABLED, /*key_id=*/2,
125 /*prefix_type=*/OutputPrefixType::TINK);
126
127 util::StatusOr<PrimitiveSet<std::string>::Entry<std::string> *> added_entry =
128 primitive_set.AddPrimitive(std::move(primitive_1.primitive),
129 primitive_1.key_info);
130 ASSERT_THAT(added_entry, IsOk());
131 ASSERT_THAT(primitive_set.set_primary(*added_entry), IsOk());
132
133 added_entry = primitive_set.AddPrimitive(std::move(primitive_2.primitive),
134 primitive_2.key_info);
135 ASSERT_THAT(added_entry, IsOk());
136
137 util::StatusOr<MonitoringKeySetInfo> monitoring_keyset_info =
138 MonitoringKeySetInfoFromPrimitiveSet(primitive_set);
139 ASSERT_THAT(monitoring_keyset_info, IsOk());
140 EXPECT_EQ(monitoring_keyset_info->GetPrimaryKeyId(), 1);
141 EXPECT_THAT(monitoring_keyset_info->GetAnnotations(),
142 UnorderedElementsAreArray(kAnnotations));
143 const std::vector<MonitoringKeySetInfo::Entry> &monitoring_entries =
144 monitoring_keyset_info->GetEntries();
145 EXPECT_THAT(
146 monitoring_entries,
147 UnorderedElementsAre(
148 MonitoringKeySetInfoEntryEq(MonitoringKeySetInfo::Entry(
149 KeyStatus::kEnabled,
150 /*key_id=*/1, "tink.SomePrimitiveInstance", "TINK")),
151 MonitoringKeySetInfoEntryEq(MonitoringKeySetInfo::Entry(
152 KeyStatus::kEnabled,
153 /*key_id=*/2, "tink.SomeOtherPrimitiveInstance", "TINK"))));
154 }
155
156 } // namespace
157 } // namespace internal
158 } // namespace tink
159 } // namespace crypto
160