Merge pull request #8125 from sfc-gh-jshim/knob-tokenless-tenant-access

Add a knob to allow token-less tenant data access for untrusted clients
This commit is contained in:
Junhyun Shim 2022-09-08 17:52:32 +02:00 committed by GitHub
commit bc47f90aff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 58 additions and 13 deletions

View File

@ -26,6 +26,7 @@
#include "fdbrpc/TokenCache.h"
#include "fdbrpc/FlowTransport.h"
#include "flow/Arena.h"
#include "flow/Knobs.h"
struct TenantInfo {
static constexpr const int64_t INVALID_TENANT = -1;
@ -69,8 +70,8 @@ struct serializable_traits<TenantInfo> : std::true_type {
static void serialize(Archiver& ar, TenantInfo& v) {
serializer(ar, v.name, v.tenantId, v.token, v.arena);
if constexpr (Archiver::isDeserializing) {
bool tenantAuthorized = false;
if (v.name.present() && v.token.present()) {
bool tenantAuthorized = FLOW_KNOBS->ALLOW_TOKENLESS_TENANT_ACCESS;
if (!tenantAuthorized && v.name.present() && v.token.present()) {
tenantAuthorized = TokenCache::instance().validate(v.name.get(), v.token.get());
}
v.trusted = FlowTransport::transport().currentDeliveryPeerIsTrusted();

View File

@ -22,6 +22,7 @@
#include <array>
#include "flow/Knobs.h"
#include "fdbclient/Knobs.h"
#include "fdbclient/ServerKnobCollection.h"
#include "fdbserver/Knobs.h"
@ -52,6 +53,9 @@ void KnobProtectiveGroup::snapshotOriginalKnobs() {
if (std::get_if<NoKnobFound>(&value)) {
value = SERVER_KNOBS->getKnob(name);
}
if (std::get_if<NoKnobFound>(&value)) {
value = FLOW_KNOBS->getKnob(name);
}
if (std::get_if<NoKnobFound>(&value)) {
ASSERT(false);
}
@ -70,4 +74,4 @@ void KnobProtectiveGroup::assignKnobs(const KnobKeyValuePairs& overrideKnobs) {
ASSERT(mutableServerKnobs.trySetKnob(name, valueRef));
TraceEvent(SevInfo, "AssignKnobValue").detail("KnobName", name).detail("KnobValue", valueRef.toString());
}
}
}

View File

@ -43,7 +43,7 @@ template <class T>
struct sfinae_true : std::true_type {};
template <class T>
auto testAuthToken(int) -> sfinae_true<decltype(std::declval<T>().getAuthToken())>;
auto testAuthToken(int) -> sfinae_true<decltype(std::declval<T>().setAuthToken(std::declval<Transaction&>()))>;
template <class>
auto testAuthToken(long) -> std::false_type;
@ -53,7 +53,7 @@ struct hasAuthToken : decltype(testAuthToken<T>(0)) {};
template <class T>
void setAuthToken(T const& self, Transaction& tr) {
if constexpr (hasAuthToken<T>::value) {
tr.setOption(FDBTransactionOptions::AUTHORIZATION_TOKEN, self.getAuthToken());
self.setAuthToken(tr);
}
}

View File

@ -1418,6 +1418,9 @@ KnobKeyValuePairs getOverriddenKnobKeyValues(const toml::value& context) {
if (std::get_if<NoKnobFound>(&parsedValue)) {
parsedValue = SERVER_KNOBS->parseKnobValue(key, value);
}
if (std::get_if<NoKnobFound>(&parsedValue)) {
parsedValue = FLOW_KNOBS->parseKnobValue(key, value);
}
if (std::get_if<NoKnobFound>(&parsedValue)) {
TraceEvent(SevError, "TestSpecUnrecognizedKnob")
.detail("KnobName", key)

View File

@ -43,6 +43,7 @@ struct CycleMembers<true> {
TenantName tenant;
authz::jwt::TokenRef token;
StringRef signedToken;
bool useToken;
};
template <bool MultiTenancy>
@ -67,6 +68,7 @@ struct CycleWorkload : TestWorkload, CycleMembers<MultiTenancy> {
minExpectedTransactionsPerSecond = transactionsPerSecond * getOption(options, "expectedRate"_sr, 0.7);
if constexpr (MultiTenancy) {
ASSERT(g_network->isSimulated());
this->useToken = getOption(options, "useToken"_sr, true);
auto k = g_simulator.authKeys.begin();
this->tenant = getOption(options, "tenant"_sr, "CycleTenant"_sr);
// make it comfortably longer than the timeout of the workload
@ -85,11 +87,6 @@ struct CycleWorkload : TestWorkload, CycleMembers<MultiTenancy> {
}
}
template <bool MT = MultiTenancy>
std::enable_if_t<MT, StringRef> getAuthToken() const {
return this->signedToken;
}
std::string description() const override {
if constexpr (MultiTenancy) {
return "TenantCycleWorkload";
@ -151,12 +148,13 @@ struct CycleWorkload : TestWorkload, CycleMembers<MultiTenancy> {
}
template <bool B = MultiTenancy>
std::enable_if_t<B> setAuthToken(Transaction& tr) {
tr.setOption(FDBTransactionOptions::AUTHORIZATION_TOKEN, this->signedToken);
std::enable_if_t<B> setAuthToken(Transaction& tr) const {
if (this->useToken)
tr.setOption(FDBTransactionOptions::AUTHORIZATION_TOKEN, this->signedToken);
}
template <bool B = MultiTenancy>
std::enable_if_t<!B> setAuthToken(Transaction& tr) {}
std::enable_if_t<!B> setAuthToken(Transaction& tr) const {}
ACTOR Future<Void> cycleClient(Database cx, CycleWorkload* self, double delay) {
state double lastTime = now();

View File

@ -131,6 +131,7 @@ void FlowKnobs::initialize(Randomize randomize, IsSimulated isSimulated) {
init( NETWORK_TEST_SCRIPT_MODE, false );
//Authorization
init( ALLOW_TOKENLESS_TENANT_ACCESS, false );
init( PUBLIC_KEY_FILE_MAX_SIZE, 1024 * 1024 );
init( PUBLIC_KEY_FILE_REFRESH_INTERVAL_SECONDS, 30 );
init( MAX_CACHED_EXPIRED_TOKENS, 1024 );

View File

@ -196,6 +196,7 @@ public:
bool NETWORK_TEST_SCRIPT_MODE;
// Authorization
bool ALLOW_TOKENLESS_TENANT_ACCESS;
int PUBLIC_KEY_FILE_MAX_SIZE;
int PUBLIC_KEY_FILE_REFRESH_INTERVAL_SECONDS;
int MAX_CACHED_EXPIRED_TOKENS;

View File

@ -184,6 +184,7 @@ if(WITH_PYTHON)
add_fdb_test(TEST_FILES fast/SystemRebootTestCycle.toml)
add_fdb_test(TEST_FILES fast/TaskBucketCorrectness.toml)
add_fdb_test(TEST_FILES fast/TenantCycle.toml)
add_fdb_test(TEST_FILES fast/TenantCycleTokenless.toml)
add_fdb_test(TEST_FILES fast/TenantEntryCache.toml)
add_fdb_test(TEST_FILES fast/TimeKeeperCorrectness.toml)
add_fdb_test(TEST_FILES fast/TxnStateStoreCycleTest.toml)

View File

@ -0,0 +1,36 @@
[configuration]
allowDefaultTenant = false
allowDisablingTenants = false
[[knobs]]
allow_tokenless_tenant_access = true
[[test]]
testTitle = 'TenantCreation'
[[test.workload]]
testName = 'CreateTenant'
name = 'First'
[[test.workload]]
testName = 'CreateTenant'
name = 'Second'
[[test]]
testTitle = 'Cycle'
[[test.workload]]
testName = 'TenantCycle'
tenant = 'First'
transactionsPerSecond = 250.0
testDuration = 10.0
expectedRate = 0.80
useToken = false
[[test.workload]]
testName = 'TenantCycle'
tenant = 'Second'
transactionsPerSecond = 2500.0
testDuration = 10.0
expectedRate = 0.80
useToken = false