TEST_F(CacheReaderTest, GetKeyShouldReturnCorrectKeyAfterRefresh) { auto catalogClient = Grid::get(operationContext())->catalogClient(operationContext()); KeysCollectionCacheReader reader("test", catalogClient); KeysCollectionDocument origKey1( 1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), NamespaceString(KeysCollectionDocument::ConfigNS), origKey1.toBSON())); auto refreshStatus = reader.refresh(operationContext()); ASSERT_OK(refreshStatus.getStatus()); { auto key = refreshStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } auto status = reader.getKey(LogicalTime(Timestamp(1, 0))); ASSERT_OK(status.getStatus()); { auto key = status.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } }
TEST_F(KeysManagerShardedTest, GetKeyWithMultipleKeys) { keyManager()->startMonitoring(getServiceContext()); KeysCollectionDocument origKey1( 1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON())); KeysCollectionDocument origKey2( 2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(205, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON())); auto keyStatus = keyManager()->getKeyForValidation(operationContext(), 1, LogicalTime(Timestamp(100, 0))); ASSERT_OK(keyStatus.getStatus()); auto key = keyStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); keyStatus = keyManager()->getKeyForValidation(operationContext(), 2, LogicalTime(Timestamp(100, 0))); ASSERT_OK(keyStatus.getStatus()); key = keyStatus.getValue(); ASSERT_EQ(2, key.getKeyId()); ASSERT_EQ(origKey2.getKey(), key.getKey()); ASSERT_EQ(Timestamp(205, 0), key.getExpiresAt().asTimestamp()); }
TEST_F(KeysManagerShardedTest, GetKeyForSigningShouldReturnRightOldKey) { keyManager()->startMonitoring(getServiceContext()); KeysCollectionDocument origKey1( 1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON())); KeysCollectionDocument origKey2( 2, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON())); keyManager()->refreshNow(operationContext()); { auto keyStatus = keyManager()->getKeyForSigning(nullptr, LogicalTime(Timestamp(100, 0))); ASSERT_OK(keyStatus.getStatus()); auto key = keyStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } { auto keyStatus = keyManager()->getKeyForSigning(nullptr, LogicalTime(Timestamp(105, 0))); ASSERT_OK(keyStatus.getStatus()); auto key = keyStatus.getValue(); ASSERT_EQ(2, key.getKeyId()); ASSERT_EQ(origKey2.getKey(), key.getKey()); ASSERT_EQ(Timestamp(110, 0), key.getExpiresAt().asTimestamp()); } }
TEST_F(CacheReaderTest, RefreshCanIncrementallyGetNewKeys) { auto catalogClient = Grid::get(operationContext())->catalogClient(operationContext()); KeysCollectionCacheReader reader("test", catalogClient); KeysCollectionDocument origKey0( 0, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(100, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), NamespaceString(KeysCollectionDocument::ConfigNS), origKey0.toBSON())); { auto refreshStatus = reader.refresh(operationContext()); ASSERT_OK(refreshStatus.getStatus()); auto key = refreshStatus.getValue(); ASSERT_EQ(0, key.getKeyId()); ASSERT_EQ(origKey0.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(100, 0), key.getExpiresAt().asTimestamp()); auto keyStatus = reader.getKey(LogicalTime(Timestamp(112, 1))); ASSERT_EQ(ErrorCodes::KeyNotFound, keyStatus.getStatus()); } KeysCollectionDocument origKey1( 1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), NamespaceString(KeysCollectionDocument::ConfigNS), origKey1.toBSON())); KeysCollectionDocument origKey2( 2, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), NamespaceString(KeysCollectionDocument::ConfigNS), origKey2.toBSON())); { auto refreshStatus = reader.refresh(operationContext()); ASSERT_OK(refreshStatus.getStatus()); auto key = refreshStatus.getValue(); ASSERT_EQ(2, key.getKeyId()); ASSERT_EQ(origKey2.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(110, 0), key.getExpiresAt().asTimestamp()); } { auto keyStatus = reader.getKey(LogicalTime(Timestamp(108, 1))); auto key = keyStatus.getValue(); ASSERT_EQ(2, key.getKeyId()); ASSERT_EQ(origKey2.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(110, 0), key.getExpiresAt().asTimestamp()); } }
TEST_F(KeysManagerShardedTest, ShouldStillBeAbleToUpdateCacheEvenIfItCantCreateKeys) { KeysCollectionDocument origKey1( 1, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON())); // Set the time to be very ahead so the updater will be forced to create new keys. const LogicalTime fakeTime(Timestamp(20000, 0)); LogicalClock::get(operationContext())->setClusterTimeFromTrustedSource(fakeTime); FailPointEnableBlock failWriteBlock("failCollectionInserts"); { FailPointEnableBlock failQueryBlock("planExecutorAlwaysFails"); keyManager()->startMonitoring(getServiceContext()); keyManager()->enableKeyGenerator(operationContext(), true); } auto keyStatus = keyManager()->getKeyForValidation(operationContext(), 1, LogicalTime(Timestamp(100, 0))); ASSERT_OK(keyStatus.getStatus()); auto key = keyStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); }
__INLINE String ElementRef::getPIName () { AssertBug(isPI(), "Element is not a PI !\n"); const char* piName = getKeyCache().getLocalKey(KeyCache::getLocalKeyId(getKeyId())); return String(piName); }
TEST_F(CacheReaderTest, RefreshShouldNotGetKeysForOtherPurpose) { auto catalogClient = Grid::get(operationContext())->catalogClient(operationContext()); KeysCollectionCacheReader reader("test", catalogClient); KeysCollectionDocument origKey0( 0, "dummy", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(100, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), NamespaceString(KeysCollectionDocument::ConfigNS), origKey0.toBSON())); { auto refreshStatus = reader.refresh(operationContext()); ASSERT_EQ(ErrorCodes::KeyNotFound, refreshStatus.getStatus()); auto emptyKeyStatus = reader.getKey(LogicalTime(Timestamp(50, 0))); ASSERT_EQ(ErrorCodes::KeyNotFound, emptyKeyStatus.getStatus()); } KeysCollectionDocument origKey1( 1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), NamespaceString(KeysCollectionDocument::ConfigNS), origKey1.toBSON())); { auto refreshStatus = reader.refresh(operationContext()); ASSERT_OK(refreshStatus.getStatus()); auto key = refreshStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } auto keyStatus = reader.getKey(LogicalTime(Timestamp(60, 1))); ASSERT_OK(keyStatus.getStatus()); { auto key = keyStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } }
Snapshot Image::snapshot() { Data img = image(); Snapshot res = creator->createSnapshot(img.get(), img.size(), getEncodingId()); res.setEncodingExtType(getEncodingExtType()); res.setEncodingZipType(getEncodingZipType()); res.setEncodingByteOrder(getEncodingByteOrder()); res.setProvider(getProvider()); res.setKeyId(getKeyId()); return res; }
TEST_F(CacheTest, GetKeyShouldReturnOldestKeyPossible) { KeysCollectionCache cache("test", catalogClient()); KeysCollectionDocument origKey0( 0, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(100, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey0.toBSON())); KeysCollectionDocument origKey1( 1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON())); KeysCollectionDocument origKey2( 2, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(110, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey2.toBSON())); auto refreshStatus = cache.refresh(operationContext()); ASSERT_OK(refreshStatus.getStatus()); { auto key = refreshStatus.getValue(); ASSERT_EQ(2, key.getKeyId()); ASSERT_EQ(origKey2.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(110, 0), key.getExpiresAt().asTimestamp()); } auto keyStatus = cache.getKey(LogicalTime(Timestamp(103, 1))); ASSERT_OK(keyStatus.getStatus()); { auto key = keyStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } }
StatusWith<KeysCollectionDocument> KeysCollectionManagerDirect::getKeyForSigning( OperationContext* opCtx, const LogicalTime& forThisTime) { // Search through the cache for active keys. { stdx::lock_guard<stdx::mutex> lk(_mutex); for (auto& it : _cache) { auto keyDoc = it.second; auto expiration = keyDoc.getExpiresAt(); if (expiration > forThisTime) { return keyDoc; } } } // Query admin.system.keys for active keys. DBDirectClient client(opCtx); BSONObjBuilder queryBuilder; queryBuilder.append("purpose", _purpose); queryBuilder.append("expiresAt", BSON("$gt" << forThisTime.asTimestamp())); auto cursor = client.query(KeysCollectionDocument::ConfigNS, queryBuilder.obj()); if (!cursor->more()) { return {ErrorCodes::KeyNotFound, "Could not find an active key for signing"}; } // Parse and return the key. auto res = KeysCollectionDocument::fromBSON(cursor->next()); if (!res.isOK()) { return res.getStatus(); } auto keyDoc = res.getValue(); // Add to our cache. { stdx::lock_guard<stdx::mutex> lk(_mutex); _cache.add(keyDoc.getKeyId(), keyDoc); } return keyDoc; }
TEST_F(CacheTest, GetKeyShouldReturnErrorIfNoKeyIsValidForGivenTime) { KeysCollectionCache cache("test", catalogClient()); KeysCollectionDocument origKey1( 1, "test", TimeProofService::generateRandomKey(), LogicalTime(Timestamp(105, 0))); ASSERT_OK(insertToConfigCollection( operationContext(), KeysCollectionDocument::ConfigNS, origKey1.toBSON())); auto refreshStatus = cache.refresh(operationContext()); ASSERT_OK(refreshStatus.getStatus()); { auto key = refreshStatus.getValue(); ASSERT_EQ(1, key.getKeyId()); ASSERT_EQ(origKey1.getKey(), key.getKey()); ASSERT_EQ("test", key.getPurpose()); ASSERT_EQ(Timestamp(105, 0), key.getExpiresAt().asTimestamp()); } auto status = cache.getKey(LogicalTime(Timestamp(110, 0))); ASSERT_EQ(ErrorCodes::KeyNotFound, status.getStatus()); }
__INLINE String ElementRef::getKey () { KeyId keyId = getKeyId(); if (KeyCache::getNamespaceId(keyId)) { LocalKeyId prefixId = getNamespacePrefix(KeyCache::getNamespaceId(keyId), true); String s; if (prefixId == getKeyCache().getBuiltinKeys().nons.xmlns() || prefixId == 0) { s += "{"; s += getKeyCache().getNamespaceURL(KeyCache::getNamespaceId(keyId)); s += "}"; } else { s += getKeyCache().getLocalKey(prefixId); } s += ":"; s += getKeyCache().getLocalKey(KeyCache::getLocalKeyId(keyId)); return s; } return getKeyCache().getLocalKey(keyId); }
DocumentMeta::DocumentMeta (const ElementRef& element) : ElementRef(element) { AssertBug(*this, "Element not defined !\n"); AssertBug(getKeyId() == __xemint.document_meta(), "Element is not a document meta !"); }
__INLINE NamespaceId ElementRef::getNamespaceId () { return getKeyCache().getNamespaceId(getKeyId()); }
__INLINE bool ElementRef::isText () { return getKeyId() == getKeyCache().getBuiltinKeys().xemint.textnode(); }
__INLINE bool ElementRef::isComment () { return getKeyId() == getKeyCache().getBuiltinKeys().xemint.comment(); }
/** * Modifiers */ __INLINE void ElementRef::addAttr (AttributeRef& attr) { #if PARANOID AssertBug ( &document == &(attr.document), "AttributeRef and ElementRef do not have the same document !\n" ); AssertBug ( attr.getParentElementPtr() == NullPtr || attr.getParentElementPtr() == getElementPtr(), "AttributeRef already added to another ElementRef \n" ); AssertBug ( attr.getAttributePtr() != NullPtr, "AttributeRef not defined !\n" ); #endif for (AttributeRef myAttr = getFirstAttr(); myAttr; myAttr = myAttr.getNext()) { if (myAttr.getKeyId() == attr.getKeyId() && myAttr.getAttributeType() == attr.getAttributeType()) { NotImplemented("Duplicate attributes : key=%x:%s, type=%x, attribute=%s\n", myAttr.getKeyId(), myAttr.getKey().c_str(), myAttr.getAttributeType(), myAttr.generateVersatileXPath().c_str()); } } ElementSegment* me = getMe<Write>(); __checkElementFlag_HasAttributesAndChildren(me->flags); if (attr.getAttributeType() == AttributeType_NamespaceAlias && !(me->flags & ElementFlag_HasNamespaceAlias)) { getDocumentAllocator().alter(me); me->flags |= ElementFlag_HasNamespaceAlias; getDocumentAllocator().protect(me); } SegmentPtr nextAttrPtr = NullPtr; if (me->attributesAndChildren.attrPtr == NullPtr) { getDocumentAllocator().alter(me); me->attributesAndChildren.attrPtr = attr.getAttributePtr(); getDocumentAllocator().protect(me); } else { SegmentPtr lastAttrPtr = me->attributesAndChildren.attrPtr; AttributeSegment* lastAttrSeg = getDocumentAllocator().getSegment<AttributeSegment, Read>(lastAttrPtr); while (lastAttrSeg->nextPtr != NullPtr) { lastAttrPtr = lastAttrSeg->nextPtr; lastAttrSeg = getDocumentAllocator().getSegment<AttributeSegment, Read>(lastAttrPtr); } getDocumentAllocator().authorizeWrite(lastAttrPtr, lastAttrSeg); getDocumentAllocator().alter(lastAttrSeg); lastAttrSeg->nextPtr = attr.getAttributePtr(); getDocumentAllocator().protect(lastAttrSeg); } AttributeSegment * attrSeg = getDocumentAllocator().getSegment<AttributeSegment, Read>(attr.getAttributePtr()); getDocumentAllocator().alter(attrSeg); attrSeg->nextPtr = nextAttrPtr; getDocumentAllocator().protect(attrSeg); attr.setParentElementPtr(getElementPtr()); Log_Element ( "Added attr on elementRef=%llx:%x (%llx, ref at %p), attr=%x (elt=%llx,attr=%llx, ref at %p)\n", getElementId(), getKeyId(), getElementPtr(), this, attr.getKeyId(), attr.getParentElementPtr(), attr.getAttributePtr(), &attr ); if (attr.isBaseType()) { getDocument().appendJournal(*this, JournalOperation_UpdateAttribute, *this, attr.getKeyId()); } }
__INLINE bool ElementRef::isPI () { return KeyCache::getNamespaceId(getKeyId()) == getKeyCache().getBuiltinKeys().xemint_pi.ns(); }