blob: 5e8b5350b1874403e953551ef5f1b679e2f72df2 [file]
/*
* Copyright 2026-present Alibaba Inc.
*
* Licensed 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