| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you 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. | |
| */ | |
| #include "paimon/common/utils/sensitive_config_utils.h" | |
| #include <map> | |
| #include <string> | |
| #include "gtest/gtest.h" | |
| #include "paimon/testing/utils/testharness.h" | |
| namespace paimon::test { | |
| TEST(SensitiveConfigUtilsTest, IsSensitiveKey) { | |
| // the key is matched lower-cased and stripped of separators, so the same marker hits | |
| // whichever separator style a key uses | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("token")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("dlf.access-key-secret")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("fs.s3a.access.key")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("fs.azure.account-key.store1")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("accessKeySecret")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("client.credential")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("fs.azure.sas.container")); | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("HTTP.Authorization")); | |
| // the match is a substring one, so a key merely naming a credential is masked too | |
| ASSERT_TRUE(SensitiveConfigUtils::IsSensitiveKey("token.provider")); | |
| ASSERT_FALSE(SensitiveConfigUtils::IsSensitiveKey("")); | |
| ASSERT_FALSE(SensitiveConfigUtils::IsSensitiveKey("uri")); | |
| ASSERT_FALSE(SensitiveConfigUtils::IsSensitiveKey("file.format")); | |
| // "signature" marks free-form text, not an option key: in a key it names the signing | |
| // algorithm rather than a stored credential | |
| ASSERT_FALSE(SensitiveConfigUtils::IsSensitiveKey("dlf.signing-algorithm")); | |
| } | |
| TEST(SensitiveConfigUtilsTest, RedactValue) { | |
| // a key naming no credential keeps its value | |
| ASSERT_EQ("orc", SensitiveConfigUtils::RedactValue("file.format", "orc")); | |
| ASSERT_EQ("v", SensitiveConfigUtils::RedactValue("", "v")); | |
| // a key naming a true secret is masked as a whole, however long the value is | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactValue("token", "bearer-credential-1")); | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactValue("dlf.access-key-secret", "secret-value-1")); | |
| // an identifier-like key keeps the last four characters of a long enough value, so | |
| // two credentials can be told apart without disclosing either | |
| ASSERT_EQ("****k-id", SensitiveConfigUtils::RedactValue("dlf.access-key-id", "an-access-k-id")); | |
| // a short value would reveal too much of itself through the tail | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactValue("dlf.access-key-id", "short-id")); | |
| } | |
| TEST(SensitiveConfigUtilsTest, RedactMap) { | |
| const std::map<std::string, std::string> options = { | |
| {"uri", "http://127.0.0.1:8080"}, | |
| {"token", "bearer-credential"}, | |
| {"dlf.access-key-secret", "ak-secret"}, | |
| {"file.format", "orc"}, | |
| }; | |
| std::map<std::string, std::string> redacted = SensitiveConfigUtils::RedactMap(options); | |
| // every key stays listed, only the credential-carrying values are replaced | |
| ASSERT_EQ(options.size(), redacted.size()); | |
| ASSERT_EQ("http://127.0.0.1:8080", redacted.at("uri")); | |
| ASSERT_EQ("orc", redacted.at("file.format")); | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, redacted.at("token")); | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, redacted.at("dlf.access-key-secret")); | |
| ASSERT_TRUE(SensitiveConfigUtils::RedactMap({}).empty()); | |
| } | |
| TEST(SensitiveConfigUtilsTest, RedactText) { | |
| // a marker anywhere in the text redacts all of it: arbitrary text cannot be masked | |
| // per-secret reliably | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactText("invalid password=abc123")); | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactText("bad ACCESS-KEY provided")); | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactText("url?X-Amz-Signature=deadbeef")); | |
| // the Azure SAS "sig" is matched literally, since it is ambiguous once the separators | |
| // are stripped | |
| ASSERT_EQ(SensitiveConfigUtils::kRedacted, | |
| SensitiveConfigUtils::RedactText("url?sig=deadbeef")); | |
| ASSERT_EQ("table t1 not found", SensitiveConfigUtils::RedactText("table t1 not found")); | |
| // a word merely containing "sig" is not a marker | |
| ASSERT_EQ("design is invalid", SensitiveConfigUtils::RedactText("design is invalid")); | |
| ASSERT_EQ("", SensitiveConfigUtils::RedactText("")); | |
| } | |
| } // namespace paimon::test |