Status V2PrivilegeDocumentParser::checkValidRoleObject( const BSONObj& roleObject) const { BSONElement roleNameElement = roleObject[ROLE_NAME_FIELD_NAME]; BSONElement roleSourceElement = roleObject[ROLE_SOURCE_FIELD_NAME]; BSONElement canDelegateElement = roleObject[ROLE_CAN_DELEGATE_FIELD_NAME]; BSONElement hasRoleElement = roleObject[ROLE_HAS_ROLE_FIELD_NAME]; if (roleNameElement.type() != String || makeStringDataFromBSONElement(roleNameElement).empty()) { return Status(ErrorCodes::UnsupportedFormat, "Role names must be non-empty strings"); } if (roleSourceElement.type() != String || makeStringDataFromBSONElement(roleSourceElement).empty()) { return Status(ErrorCodes::UnsupportedFormat, "Role source must be non-empty strings"); } if (canDelegateElement.type() != Bool) { return Status(ErrorCodes::UnsupportedFormat, "Entries in 'roles' array need a 'canDelegate' boolean field"); } if (hasRoleElement.type() != Bool) { return Status(ErrorCodes::UnsupportedFormat, "Entries in 'roles' array need a 'hasRole' boolean field"); } if (!hasRoleElement.Bool() && !canDelegateElement.Bool()) { return Status(ErrorCodes::UnsupportedFormat, "At least one of 'canDelegate' and 'hasRole' must be true for " "every role in the 'roles' array"); } return Status::OK(); }
bool BalancerPolicy::hasOpsQueued( BSONObj limits ){ BSONElement opsQueued = limits[ LimitsFields::hasOpsQueued.name() ]; if ( opsQueued.eoo() || ! opsQueued.Bool() ){ return false; } return true; }
void reload() { list<BSONObj> all; { ScopedDbConnection conn( configServer.getPrimary() ); auto_ptr<DBClientCursor> c = conn->query( ShardNS::shard , Query() ); massert( 13632 , "couldn't get updated shard list from config server" , c.get() ); while ( c->more() ) { all.push_back( c->next().getOwned() ); } conn.done(); } scoped_lock lk( _mutex ); // We use the _lookup table for all shards and for the primary config DB. The config DB info, // however, does not come from the ShardNS::shard. So when cleaning the _lookup table we leave // the config state intact. The rationale is that this way we could drop shards that // were removed without reinitializing the config DB information. map<string,Shard>::iterator i = _lookup.find( "config" ); if ( i != _lookup.end() ) { Shard config = i->second; _lookup.clear(); _lookup[ "config" ] = config; } else { _lookup.clear(); } for ( list<BSONObj>::iterator i=all.begin(); i!=all.end(); ++i ) { BSONObj o = *i; string name = o["_id"].String(); string host = o["host"].String(); long long maxSize = 0; BSONElement maxSizeElem = o[ ShardFields::maxSize.name() ]; if ( ! maxSizeElem.eoo() ) { maxSize = maxSizeElem.numberLong(); } bool isDraining = false; BSONElement isDrainingElem = o[ ShardFields::draining.name() ]; if ( ! isDrainingElem.eoo() ) { isDraining = isDrainingElem.Bool(); } Shard s( name , host , maxSize , isDraining ); _lookup[name] = s; _lookup[host] = s; // add rs name to lookup (if it exists) size_t pos; if ((pos = host.find('/', 0)) != string::npos) { _lookup[host.substr(0, pos)] = s; } } }
// PD_TRACE_DECLARE_FUNCTION ( SDB__RTNALTERCL_DOIT, "_rtnAlterCollection::doit" ) INT32 _rtnAlterCollection::doit( _pmdEDUCB *cb, _SDB_DMSCB *dmsCB, _SDB_RTNCB *rtnCB, _dpsLogWrapper *dpsCB, INT16 w, INT64 *pContextID ) { INT32 rc = SDB_OK ; PD_TRACE_ENTRY( SDB__RTNALTERCL_DOIT ) ; BSONObj idxDef ; BSONObj options ; BSONElement ensureIndex ; BSONElement shardingKey ; options = _alterObj.getField( FIELD_NAME_OPTIONS ).embeddedObject() ; shardingKey = options.getField( FIELD_NAME_SHARDINGKEY ) ; if ( Object != shardingKey.type() ) { PD_LOG( PDDEBUG, "no sharding key in the alter object, do noting." ) ; goto done ; } ensureIndex = options.getField( FIELD_NAME_ENSURE_SHDINDEX ) ; if ( Bool == ensureIndex.type() && !ensureIndex.Bool() ) { PD_LOG( PDDEBUG, "ensureShardingIndex is false, do nothing." ) ; goto done ; } idxDef = BSON( IXM_FIELD_NAME_KEY << shardingKey.embeddedObject() << IXM_FIELD_NAME_NAME << IXM_SHARD_KEY_NAME << "v"<<0 ) ; rc = rtnCreateIndexCommand( collectionFullName(), idxDef, cb, dmsCB, dpsCB, TRUE ) ; if ( SDB_IXM_REDEF == rc ) { rc = SDB_OK ; goto done ; } else if ( SDB_OK != rc ) { PD_LOG( PDERROR, "failed to create sharding key index:%d", rc ) ; goto error ; } else { /* catAgent *catAgent = sdbGetShardCB()->getCataAgent() ; catAgent->lock_w() ; catAgent->clear( collectionFullName() ) ; catAgent->release_w() ; sdbGetClsCB()->invalidateCata( collectionFullName() ) ;*/ } done: PD_TRACE_EXITRC( SDB__RTNALTERCL_DOIT, rc ) ; return rc ; error: goto done ; }
bool BalancerPolicy::isDraining( BSONObj limits ){ BSONElement draining = limits[ ShardFields::draining.name() ]; if ( draining.eoo() || ! draining.Bool() ){ return false; } return true; }
Status _checkV2RolesArray(const BSONElement& rolesElement) { if (rolesElement.eoo()) { return _badValue("User document needs 'roles' field to be provided", 0); } if (rolesElement.type() != Array) { return _badValue("'roles' field must be an array", 0); } for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) { if ((*iter).type() != Object) { return _badValue("Elements in 'roles' array must objects", 0); } BSONObj roleObj = (*iter).Obj(); BSONElement nameElement = roleObj[ROLE_NAME_FIELD_NAME]; BSONElement sourceElement = roleObj[ROLE_SOURCE_FIELD_NAME]; BSONElement canDelegateElement = roleObj[ROLE_CAN_DELEGATE_FIELD_NAME]; BSONElement hasRoleElement = roleObj[ROLE_HAS_ROLE_FIELD_NAME]; if (nameElement.type() != String || makeStringDataFromBSONElement(nameElement).empty()) { return _badValue("Entries in 'roles' array need 'name' field to be a non-empty " "string", 0); } if (sourceElement.type() != String || makeStringDataFromBSONElement(sourceElement).empty()) { return _badValue("Entries in 'roles' array need 'source' field to be a non-empty " "string", 0); } if (canDelegateElement.type() != Bool) { return _badValue("Entries in 'roles' array need a 'canDelegate' boolean field", 0); } if (hasRoleElement.type() != Bool) { return _badValue("Entries in 'roles' array need a 'canDelegate' boolean field", 0); } if (!canDelegateElement.Bool() && !hasRoleElement.Bool()) { return _badValue("At least one of 'canDelegate' and 'hasRole' must be true for " "every role in the 'roles' array", 0); } } return Status::OK(); }
/* **************************************************************************** * * addCompoundNode - * */ static void addCompoundNode(orion::CompoundValueNode* cvP, const BSONElement& e) { if ((e.type() != String) && (e.type() != Bool) && (e.type() != NumberDouble) && (e.type() != jstNULL) && (e.type() != Object) && (e.type() != Array)) { LM_E(("Runtime Error (unknown BSON type: %d)", e.type())); return; } orion::CompoundValueNode* child = new orion::CompoundValueNode(orion::ValueTypeObject); child->name = dbDotDecode(e.fieldName()); switch (e.type()) { case String: child->valueType = orion::ValueTypeString; child->stringValue = e.String(); break; case Bool: child->valueType = orion::ValueTypeBoolean; child->boolValue = e.Bool(); break; case NumberDouble: child->valueType = orion::ValueTypeNumber; child->numberValue = e.Number(); break; case jstNULL: child->valueType = orion::ValueTypeNone; break; case Object: compoundObjectResponse(child, e); break; case Array: compoundVectorResponse(child, e); break; default: // // We need the default clause to avoid 'enumeration value X not handled in switch' errors // due to -Werror=switch at compilation time // break; } cvP->add(child); }
Status V2PrivilegeDocumentParser::initializeUserRolesFromPrivilegeDocument( User* user, const BSONObj& privDoc, const StringData&) const { BSONElement rolesElement = privDoc[ROLES_FIELD_NAME]; if (rolesElement.type() != Array) { return Status(ErrorCodes::UnsupportedFormat, "User document needs 'roles' field to be an array"); } for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) { if ((*it).type() != Object) { return Status(ErrorCodes::UnsupportedFormat, "User document needs values in 'roles' array to be a sub-documents"); } BSONObj roleObject = (*it).Obj(); Status status = checkValidRoleObject(roleObject); if (!status.isOK()) { return status; } BSONElement roleNameElement = roleObject[ROLE_NAME_FIELD_NAME]; BSONElement roleSourceElement = roleObject[ROLE_SOURCE_FIELD_NAME]; BSONElement canDelegateElement = roleObject[ROLE_CAN_DELEGATE_FIELD_NAME]; BSONElement hasRoleElement = roleObject[ROLE_HAS_ROLE_FIELD_NAME]; if (hasRoleElement.Bool()) { user->addRole(RoleName(roleNameElement.String(), roleSourceElement.String())); } if (canDelegateElement.Bool()) { // TODO(spencer): record the fact that this user can delegate this role } } return Status::OK(); }
Status V2UserDocumentParser::initializeUserCredentialsFromUserDocument( User* user, const BSONObj& privDoc) const { User::CredentialData credentials; std::string userDB = privDoc[AuthorizationManager::USER_DB_FIELD_NAME].String(); BSONElement credentialsElement = privDoc[CREDENTIALS_FIELD_NAME]; if (!credentialsElement.eoo()) { if (credentialsElement.type() != Object) { return Status(ErrorCodes::UnsupportedFormat, "'credentials' field in user documents must be an object"); } if (userDB == "$external") { BSONElement externalCredentialElement = credentialsElement.Obj()[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME]; if (!externalCredentialElement.eoo()) { if (externalCredentialElement.type() != Bool || !externalCredentialElement.Bool()) { return Status(ErrorCodes::UnsupportedFormat, "'external' field in credentials object must be set to true"); } else { credentials.isExternal = true; } } else { return Status(ErrorCodes::UnsupportedFormat, "User documents defined on '$external' must provide set " "credentials to {external:true}"); } } else { const bool haveSha1 = parseSCRAMCredentials( credentialsElement, credentials.scram_sha1, SCRAMSHA1_CREDENTIAL_FIELD_NAME); const bool haveSha256 = parseSCRAMCredentials( credentialsElement, credentials.scram_sha256, SCRAMSHA256_CREDENTIAL_FIELD_NAME); if (!haveSha1 && !haveSha256) { return Status( ErrorCodes::UnsupportedFormat, "User documents must provide credentials for SCRAM-SHA-1 and/or SCRAM-SHA-256"); } credentials.isExternal = false; } } else { return Status(ErrorCodes::UnsupportedFormat, "Cannot extract credentials from user documents without a " "'credentials' field"); } user->setCredentials(credentials); return Status::OK(); }
void reload() { list<BSONObj> all; { scoped_ptr<ScopedDbConnection> conn( ScopedDbConnection::getScopedDbConnection( configServer.getPrimary().getConnString() ) ); auto_ptr<DBClientCursor> c = conn->get()->query( ShardNS::shard , Query() ); massert( 13632 , "couldn't get updated shard list from config server" , c.get() ); while ( c->more() ) { all.push_back( c->next().getOwned() ); } conn->done(); } scoped_lock lk( _mutex ); // We use the _lookup table for all shards and for the primary config DB. The config DB info, // however, does not come from the ShardNS::shard. So when cleaning the _lookup table we leave // the config state intact. The rationale is that this way we could drop shards that // were removed without reinitializing the config DB information. ShardMap::iterator i = _lookup.find( "config" ); if ( i != _lookup.end() ) { ShardPtr config = i->second; _lookup.clear(); _lookup[ "config" ] = config; } else { _lookup.clear(); } _rsLookup.clear(); for ( list<BSONObj>::iterator i=all.begin(); i!=all.end(); ++i ) { BSONObj o = *i; string name = o["_id"].String(); string host = o["host"].String(); long long maxSize = 0; BSONElement maxSizeElem = o[ ShardFields::maxSize.name() ]; if ( ! maxSizeElem.eoo() ) { maxSize = maxSizeElem.numberLong(); } bool isDraining = false; BSONElement isDrainingElem = o[ ShardFields::draining.name() ]; if ( ! isDrainingElem.eoo() ) { isDraining = isDrainingElem.Bool(); } ShardPtr s( new Shard( name , host , maxSize , isDraining ) ); if ( o["tags"].type() == Array ) { vector<BSONElement> v = o["tags"].Array(); for ( unsigned j=0; j<v.size(); j++ ) { s->addTag( v[j].String() ); } } _lookup[name] = s; _installHost( host , s ); } }
Status V2UserDocumentParser::checkValidUserDocument(const BSONObj& doc) const { auto userIdElement = doc[AuthorizationManager::USERID_FIELD_NAME]; auto userElement = doc[AuthorizationManager::USER_NAME_FIELD_NAME]; auto userDBElement = doc[AuthorizationManager::USER_DB_FIELD_NAME]; auto credentialsElement = doc[CREDENTIALS_FIELD_NAME]; auto rolesElement = doc[ROLES_FIELD_NAME]; // Validate the "userId" element. if (!userIdElement.eoo()) { if (!userIdElement.isBinData(BinDataType::newUUID)) { return _badValue("User document needs 'userId' field to be a UUID"); } } // Validate the "user" element. if (userElement.type() != String) return _badValue("User document needs 'user' field to be a string"); if (userElement.valueStringData().empty()) return _badValue("User document needs 'user' field to be non-empty"); // Validate the "db" element if (userDBElement.type() != String || userDBElement.valueStringData().empty()) { return _badValue("User document needs 'db' field to be a non-empty string"); } StringData userDBStr = userDBElement.valueStringData(); if (!NamespaceString::validDBName(userDBStr, NamespaceString::DollarInDbNameBehavior::Allow) && userDBStr != "$external") { return _badValue(mongoutils::str::stream() << "'" << userDBStr << "' is not a valid value for the db field."); } // Validate the "credentials" element if (credentialsElement.eoo()) { return _badValue("User document needs 'credentials' object"); } if (credentialsElement.type() != Object) { return _badValue("User document needs 'credentials' field to be an object"); } BSONObj credentialsObj = credentialsElement.Obj(); if (credentialsObj.isEmpty()) { return _badValue("User document needs 'credentials' field to be a non-empty object"); } if (userDBStr == "$external") { BSONElement externalElement = credentialsObj[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME]; if (externalElement.eoo() || externalElement.type() != Bool || !externalElement.Bool()) { return _badValue( "User documents for users defined on '$external' must have " "'credentials' field set to {external: true}"); } } else { const auto validateScram = [&credentialsObj](const auto& fieldName) { auto scramElement = credentialsObj[fieldName]; if (scramElement.eoo()) { return Status(ErrorCodes::NoSuchKey, str::stream() << fieldName << " does not exist"); } if (scramElement.type() != Object) { return _badValue(str::stream() << fieldName << " credential must be an object, if present"); } return Status::OK(); }; const auto sha1status = validateScram(SCRAMSHA1_CREDENTIAL_FIELD_NAME); if (!sha1status.isOK() && (sha1status.code() != ErrorCodes::NoSuchKey)) { return sha1status; } const auto sha256status = validateScram(SCRAMSHA256_CREDENTIAL_FIELD_NAME); if (!sha256status.isOK() && (sha256status.code() != ErrorCodes::NoSuchKey)) { return sha256status; } if (!sha1status.isOK() && !sha256status.isOK()) { return _badValue( "User document must provide credentials for all " "non-external users"); } } // Validate the "roles" element. Status status = _checkV2RolesArray(rolesElement); if (!status.isOK()) return status; // Validate the "authenticationRestrictions" element. status = initializeAuthenticationRestrictionsFromUserDocument(doc, nullptr); if (!status.isOK()) { return status; } return Status::OK(); }
Status V2UserDocumentParser::initializeUserCredentialsFromUserDocument( User* user, const BSONObj& privDoc) const { User::CredentialData credentials; std::string userDB = privDoc[AuthorizationManager::USER_DB_FIELD_NAME].String(); BSONElement credentialsElement = privDoc[CREDENTIALS_FIELD_NAME]; if (!credentialsElement.eoo()) { if (credentialsElement.type() != Object) { return Status(ErrorCodes::UnsupportedFormat, "'credentials' field in user documents must be an object"); } if (userDB == "$external") { BSONElement externalCredentialElement = credentialsElement.Obj()[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME]; if (!externalCredentialElement.eoo()) { if (externalCredentialElement.type() != Bool || !externalCredentialElement.Bool()) { return Status(ErrorCodes::UnsupportedFormat, "'external' field in credentials object must be set to true"); } else { credentials.isExternal = true; } } else { return Status(ErrorCodes::UnsupportedFormat, "User documents defined on '$external' must provide set " "credentials to {external:true}"); } } else { BSONElement scramElement = credentialsElement.Obj()[SCRAM_CREDENTIAL_FIELD_NAME]; BSONElement mongoCRCredentialElement = credentialsElement.Obj()[MONGODB_CR_CREDENTIAL_FIELD_NAME]; if (scramElement.eoo() && mongoCRCredentialElement.eoo()) { return Status(ErrorCodes::UnsupportedFormat, "User documents must provide credentials for SCRAM-SHA-1 " "or MONGODB-CR authentication"); } if (!scramElement.eoo()) { // We are asserting rather then returning errors since these // fields should have been prepopulated by the calling code. credentials.scram.iterationCount = scramElement.Obj()["iterationCount"].numberInt(); uassert(17501, "Invalid or missing SCRAM iteration count", credentials.scram.iterationCount > 0); credentials.scram.salt = scramElement.Obj()["salt"].str(); uassert(17502, "Missing SCRAM salt", !credentials.scram.salt.empty()); credentials.scram.serverKey = scramElement["serverKey"].str(); uassert(17503, "Missing SCRAM serverKey", !credentials.scram.serverKey.empty()); credentials.scram.storedKey = scramElement["storedKey"].str(); uassert(17504, "Missing SCRAM storedKey", !credentials.scram.storedKey.empty()); } if (!mongoCRCredentialElement.eoo()) { if (mongoCRCredentialElement.type() != String || mongoCRCredentialElement.valueStringData().empty()) { return Status(ErrorCodes::UnsupportedFormat, "MONGODB-CR credentials must be non-empty strings"); } else { credentials.password = mongoCRCredentialElement.String(); if (credentials.password.empty()) { return Status(ErrorCodes::UnsupportedFormat, "User documents must provide authentication credentials"); } } } credentials.isExternal = false; } } else { return Status(ErrorCodes::UnsupportedFormat, "Cannot extract credentials from user documents without a " "'credentials' field"); } user->setCredentials(credentials); return Status::OK(); }
Status V2UserDocumentParser::checkValidUserDocument(const BSONObj& doc) const { BSONElement userElement = doc[AuthorizationManager::USER_NAME_FIELD_NAME]; BSONElement userDBElement = doc[AuthorizationManager::USER_DB_FIELD_NAME]; BSONElement credentialsElement = doc[CREDENTIALS_FIELD_NAME]; BSONElement rolesElement = doc[ROLES_FIELD_NAME]; // Validate the "user" element. if (userElement.type() != String) return _badValue("User document needs 'user' field to be a string", 0); if (userElement.valueStringData().empty()) return _badValue("User document needs 'user' field to be non-empty", 0); // Validate the "db" element if (userDBElement.type() != String || userDBElement.valueStringData().empty()) { return _badValue("User document needs 'db' field to be a non-empty string", 0); } StringData userDBStr = userDBElement.valueStringData(); if (!NamespaceString::validDBName(userDBStr) && userDBStr != "$external") { return _badValue(mongoutils::str::stream() << "'" << userDBStr << "' is not a valid value for the db field.", 0); } // Validate the "credentials" element if (credentialsElement.eoo()) { return _badValue("User document needs 'credentials' object", 0); } if (credentialsElement.type() != Object) { return _badValue("User document needs 'credentials' field to be an object", 0); } BSONObj credentialsObj = credentialsElement.Obj(); if (credentialsObj.isEmpty()) { return _badValue("User document needs 'credentials' field to be a non-empty object", 0); } if (userDBStr == "$external") { BSONElement externalElement = credentialsObj[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME]; if (externalElement.eoo() || externalElement.type() != Bool || !externalElement.Bool()) { return _badValue("User documents for users defined on '$external' must have " "'credentials' field set to {external: true}", 0); } } else { BSONElement scramElement = credentialsObj[SCRAM_CREDENTIAL_FIELD_NAME]; BSONElement mongoCRElement = credentialsObj[MONGODB_CR_CREDENTIAL_FIELD_NAME]; if (!mongoCRElement.eoo()) { if (mongoCRElement.type() != String || mongoCRElement.valueStringData().empty()) { return _badValue("MONGODB-CR credential must to be a non-empty string" ", if present", 0); } } else if (!scramElement.eoo()) { if (scramElement.type() != Object) { return _badValue("SCRAM credential must be an object, if present", 0); } } else { return _badValue("User document must provide credentials for all " "non-external users", 0); } } // Validate the "roles" element. Status status = _checkV2RolesArray(rolesElement); if (!status.isOK()) return status; return Status::OK(); }