mirror of
https://github.com/apple/foundationdb.git
synced 2025-06-02 19:25:52 +08:00
addressed review comments
This commit is contained in:
parent
f268265d96
commit
2ae17233d8
@ -3146,6 +3146,8 @@ SpanContext generateSpanID(bool transactionTracingSample, SpanContext parentCont
|
||||
deterministicRandom()->randomUniqueID(), deterministicRandom()->randomUInt64(), TraceFlags::unsampled);
|
||||
}
|
||||
|
||||
FDB_DEFINE_BOOLEAN_PARAM(AllowInvalidTenantID);
|
||||
|
||||
TransactionState::TransactionState(Database cx,
|
||||
Optional<TenantName> tenant,
|
||||
TaskPriority taskID,
|
||||
@ -3174,7 +3176,7 @@ Reference<TransactionState> TransactionState::cloneAndReset(Reference<Transactio
|
||||
return newState;
|
||||
}
|
||||
|
||||
TenantInfo TransactionState::getTenantInfo(bool allowInvalidId /* = false */) {
|
||||
TenantInfo TransactionState::getTenantInfo(AllowInvalidTenantID allowInvalidId /* = false */) {
|
||||
Optional<TenantName> const& t = tenant();
|
||||
|
||||
if (options.rawAccess) {
|
||||
|
@ -235,6 +235,8 @@ struct Watch : public ReferenceCounted<Watch>, NonCopyable {
|
||||
void setWatch(Future<Void> watchFuture);
|
||||
};
|
||||
|
||||
FDB_DECLARE_BOOLEAN_PARAM(AllowInvalidTenantID);
|
||||
|
||||
struct TransactionState : ReferenceCounted<TransactionState> {
|
||||
Database cx;
|
||||
int64_t tenantId = TenantInfo::INVALID_TENANT;
|
||||
@ -270,7 +272,7 @@ struct TransactionState : ReferenceCounted<TransactionState> {
|
||||
Reference<TransactionLogInfo> trLogInfo);
|
||||
|
||||
Reference<TransactionState> cloneAndReset(Reference<TransactionLogInfo> newTrLogInfo, bool generateNewSpan) const;
|
||||
TenantInfo getTenantInfo(bool allowInvalidId = false);
|
||||
TenantInfo getTenantInfo(AllowInvalidTenantID allowInvalidId = AllowInvalidTenantID::False);
|
||||
|
||||
Optional<TenantName> const& tenant();
|
||||
bool hasTenant() const;
|
||||
|
@ -17,6 +17,7 @@ struct TokenCacheImpl {
|
||||
TokenCacheImpl() : cache(FLOW_KNOBS->TOKEN_CACHE_SIZE) {}
|
||||
|
||||
bool validate(TenantNameRef tenant, StringRef token);
|
||||
bool validateAndAdd(double currentTime, StringRef signature, StringRef token, NetworkAddress const& peer);
|
||||
};
|
||||
|
||||
TokenCache::TokenCache() : impl(new TokenCacheImpl()) {}
|
||||
@ -36,65 +37,88 @@ bool TokenCache::validate(TenantNameRef name, StringRef token) {
|
||||
return impl->validate(name, token);
|
||||
}
|
||||
|
||||
bool TokenCacheImpl::validateAndAdd(double currentTime,
|
||||
StringRef signature,
|
||||
StringRef token,
|
||||
NetworkAddress const& peer) {
|
||||
Arena arena;
|
||||
authz::jwt::TokenRef t;
|
||||
if (!authz::jwt::parseToken(arena, t, token)) {
|
||||
TEST(true); // Token can't be parsed
|
||||
return false;
|
||||
}
|
||||
if (!t.keyId.present()) {
|
||||
TEST(true); // Token with no key id
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoKeyID");
|
||||
return false;
|
||||
}
|
||||
auto key = FlowTransport::transport().getPublicKeyByName(t.keyId.get());
|
||||
if (!key.present()) {
|
||||
TEST(true); // Token referencing non-existing key
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "UnknownKey");
|
||||
return false;
|
||||
} else if (!t.expiresAtUnixTime.present()) {
|
||||
TEST(true); // Token has no expiration time
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoExpirationTime");
|
||||
return false;
|
||||
} else if (double(t.expiresAtUnixTime.get()) <= currentTime) {
|
||||
TEST(true); // Expired token
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "Expired");
|
||||
return false;
|
||||
} else if (!t.notBeforeUnixTime.present()) {
|
||||
TEST(true); // Token has no not-before field
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoNotBefore");
|
||||
return false;
|
||||
} else if (double(t.notBeforeUnixTime.get()) > currentTime) {
|
||||
TEST(true); // Token has no not-before field
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "TokenNotYetValid");
|
||||
return false;
|
||||
} else if (!t.tenants.present()) {
|
||||
TEST(true); // Token with no tenants
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoTenants");
|
||||
return false;
|
||||
} else if (!authz::jwt::verifyToken(token, key.get())) {
|
||||
TEST(true); // Token with invalid signature
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "InvalidSignature");
|
||||
return false;
|
||||
} else {
|
||||
CacheEntry c;
|
||||
c.expirationTime = double(t.expiresAtUnixTime.get());
|
||||
for (auto tenant : t.tenants.get()) {
|
||||
c.tenants.insert(StringRef(c.arena, tenant));
|
||||
}
|
||||
StringRef signature(c.arena, signature);
|
||||
cache.insert(signature, c);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool TokenCacheImpl::validate(TenantNameRef name, StringRef token) {
|
||||
auto sig = authz::jwt::signaturePart(token);
|
||||
auto cachedEntry = cache.get(sig);
|
||||
double currentTime = g_network->timer();
|
||||
NetworkAddress peer = FlowTransport::transport().currentDeliveryPeerAddress();
|
||||
|
||||
if (cachedEntry.has_value()) {
|
||||
auto& entry = cachedEntry.get();
|
||||
if (entry.expirationTime > currentTime) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "Expired");
|
||||
throw permission_denied();
|
||||
}
|
||||
if (entry.tenants.count(name) == 0) {
|
||||
TraceEvent(SevWarn, "TenantTokenMismatch").detail("From", peer).detail("Tenant", name.toString());
|
||||
throw permission_denied();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
Arena arena;
|
||||
authz::jwt::TokenRef t;
|
||||
if (!authz::jwt::parseToken(arena, t, token)) {
|
||||
throw permission_denied();
|
||||
}
|
||||
if (!t.keyId.present()) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoKeyID");
|
||||
return false;
|
||||
}
|
||||
auto key = FlowTransport::transport().getPublicKeyByName(t.keyId.get());
|
||||
if (key.present() && authz::jwt::verifyToken(token, key.get())) {
|
||||
if (!t.expiresAtUnixTime.present()) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoExpirationTime");
|
||||
throw permission_denied();
|
||||
} else if (double(t.expiresAtUnixTime.get()) <= currentTime) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "Expired");
|
||||
return false;
|
||||
}
|
||||
if (!t.notBeforeUnixTime.present()) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoNotBefore");
|
||||
return false;
|
||||
} else if (double(t.notBeforeUnixTime.get()) > currentTime) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "TokenNotYetValid");
|
||||
return false;
|
||||
}
|
||||
if (!t.tenants.present()) {
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "NoTenants");
|
||||
return false;
|
||||
}
|
||||
CacheEntry c;
|
||||
c.expirationTime = double(t.expiresAtUnixTime.get());
|
||||
for (auto tenant : t.tenants.get()) {
|
||||
c.tenants.insert(StringRef(c.arena, tenant));
|
||||
}
|
||||
StringRef signature(c.arena, sig);
|
||||
return true;
|
||||
if (!cachedEntry.has_value()) {
|
||||
if (validateAndAdd(currentTime, sig, token, peer)) {
|
||||
cachedEntry = cache.get(sig);
|
||||
} else {
|
||||
TraceEvent(SevWarn, "InvalidSignature")
|
||||
.detail("From", peer)
|
||||
.detail("Reason", key.present() ? "VerificationFailed" : "KeyNotFound");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(cachedEntry.has_value());
|
||||
|
||||
auto& entry = cachedEntry.get();
|
||||
if (entry.expirationTime < currentTime) {
|
||||
TEST(true); // Read expired token from cache
|
||||
TraceEvent(SevWarn, "InvalidToken").detail("From", peer).detail("Reason", "Expired");
|
||||
return false;
|
||||
}
|
||||
if (entry.tenants.count(name) == 0) {
|
||||
TEST(true); // Valid token doesn't reference tenant
|
||||
TraceEvent(SevWarn, "TenantTokenMismatch").detail("From", peer).detail("Tenant", name.toString());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user