diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2021-06-10 10:56:13 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-06-10 15:55:54 +0000 |
commit | f2643946a9253a2accc8f3b0b8a95ee2fd84f22c (patch) | |
tree | f98d63fe0d0326d6f3bc679247cca5ae6dfa3981 /src/mongo/db/auth/privilege_parser.cpp | |
parent | 7f56da83d8ce91fa17bd5687a33747fe34e64cf8 (diff) | |
download | mongo-f2643946a9253a2accc8f3b0b8a95ee2fd84f22c.tar.gz |
SERVER-56444 Grant read/write access on time-series buckets collections to admin roles
Diffstat (limited to 'src/mongo/db/auth/privilege_parser.cpp')
-rw-r--r-- | src/mongo/db/auth/privilege_parser.cpp | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/src/mongo/db/auth/privilege_parser.cpp b/src/mongo/db/auth/privilege_parser.cpp index 7fb7ea38008..4d7bb9072c2 100644 --- a/src/mongo/db/auth/privilege_parser.cpp +++ b/src/mongo/db/auth/privilege_parser.cpp @@ -45,6 +45,7 @@ using str::stream; const BSONField<bool> ParsedResource::anyResource("anyResource"); const BSONField<bool> ParsedResource::cluster("cluster"); +const BSONField<string> ParsedResource::systemBuckets("system_buckets"); const BSONField<string> ParsedResource::db("db"); const BSONField<string> ParsedResource::collection("collection"); @@ -65,14 +66,20 @@ bool ParsedResource::isValid(std::string* errMsg) const { ++numCandidateTypes; if (isClusterSet()) ++numCandidateTypes; - if (isDbSet() || isCollectionSet()) + if (isDbSet() || isCollectionSet() || isSystemBucketsSet()) ++numCandidateTypes; - if (isDbSet() != isCollectionSet()) { + if (!isSystemBucketsSet() && isDbSet() != isCollectionSet()) { *errMsg = stream() << "resource must set both " << db.name() << " and " << collection.name() << " or neither, but not exactly one."; return false; + } else if (isSystemBucketsSet()) { + if (isCollectionSet()) { + *errMsg = stream() << "system_buckets and collection cannot both be set"; + return false; + } } + if (numCandidateTypes != 1) { *errMsg = stream() << "resource must have exactly " << db.name() << " and " << collection.name() << " set, or have only " << cluster.name() @@ -80,20 +87,24 @@ bool ParsedResource::isValid(std::string* errMsg) const { << " or have only " << anyResource.name() << " set"; return false; } + if (isAnyResourceSet() && !getAnyResource()) { *errMsg = stream() << anyResource.name() << " must be true when specified"; return false; } + if (isClusterSet() && !getCluster()) { *errMsg = stream() << cluster.name() << " must be true when specified"; return false; } + if (isDbSet() && (!NamespaceString::validDBName(getDb(), NamespaceString::DollarInDbNameBehavior::Allow) && !getDb().empty())) { *errMsg = stream() << getDb() << " is not a valid database name"; return false; } + if (isCollectionSet() && (!NamespaceString::validCollectionName(getCollection()) && !getCollection().empty())) { // local.oplog.$main is a real collection that the server will create. But, collection @@ -104,6 +115,7 @@ bool ParsedResource::isValid(std::string* errMsg) const { return false; } } + return true; } @@ -116,6 +128,9 @@ BSONObj ParsedResource::toBSON() const { if (_isClusterSet) builder.append(cluster(), _cluster); + if (_isSystemBucketsSet) + builder.append(systemBuckets(), _systemBuckets); + if (_isDbSet) builder.append(db(), _db); @@ -143,6 +158,11 @@ bool ParsedResource::parseBSON(const BSONObj& source, string* errMsg) { return false; _isClusterSet = fieldState == FieldParser::FIELD_SET; + fieldState = FieldParser::extract(source, systemBuckets, &_systemBuckets, errMsg); + if (fieldState == FieldParser::FIELD_INVALID) + return false; + _isSystemBucketsSet = fieldState == FieldParser::FIELD_SET; + fieldState = FieldParser::extract(source, db, &_db, errMsg); if (fieldState == FieldParser::FIELD_INVALID) return false; @@ -163,6 +183,9 @@ void ParsedResource::clear() { _cluster = false; _isClusterSet = false; + _systemBuckets.clear(); + _isSystemBucketsSet = false; + _db.clear(); _isDbSet = false; @@ -179,6 +202,9 @@ void ParsedResource::cloneTo(ParsedResource* other) const { other->_cluster = _cluster; other->_isClusterSet = _isClusterSet; + other->_systemBuckets = _systemBuckets; + other->_isSystemBucketsSet = _isSystemBucketsSet; + other->_db = _db; other->_isDbSet = _isDbSet; @@ -226,6 +252,24 @@ bool ParsedResource::getCluster() const { return _cluster; } +void ParsedResource::setSystemBuckets(StringData collection) { + _systemBuckets = collection.toString(); + _isSystemBucketsSet = true; +} + +void ParsedResource::unsetSystemBuckets() { + _isSystemBucketsSet = false; +} + +bool ParsedResource::isSystemBucketsSet() const { + return _isSystemBucketsSet; +} + +const std::string& ParsedResource::getSystemBuckets() const { + dassert(_isSystemBucketsSet); + return _systemBuckets; +} + void ParsedResource::setDb(StringData db) { _db = db.toString(); _isDbSet = true; @@ -419,6 +463,40 @@ Status ParsedPrivilege::parsedPrivilegeToPrivilege(const ParsedPrivilege& parsed resource = ResourcePattern::forAnyResource(); } else if (parsedResource.isClusterSet() && parsedResource.getCluster()) { resource = ResourcePattern::forClusterResource(); + } else if (parsedResource.isSystemBucketsSet()) { + if (parsedResource.isDbSet()) { + if (parsedResource.getDb().empty()) { + if (parsedResource.getSystemBuckets().empty()) { + // {db: "", system_buckets: ""} - match any system buckets in any db + resource = ResourcePattern::forAnySystemBuckets(); + } else { + // {db: "", system_buckets: "<coll>"} - match any system.buckets.<coll> in + // any db + resource = ResourcePattern::forAnySystemBucketsInAnyDatabase( + parsedResource.getSystemBuckets()); + } + } else { + if (parsedResource.getSystemBuckets().empty()) { + // {db: "<db>", system_buckets: ""} - match any system buckets in db <db> + resource = + ResourcePattern::forAnySystemBucketsInDatabase(parsedResource.getDb()); + } else { + // {db: "<db>", system_buckets: "<coll>"} - match <db>.system.buckets.<coll> + resource = ResourcePattern::forExactSystemBucketsCollection( + parsedResource.getDb(), parsedResource.getSystemBuckets()); + } + } + } else { + if (parsedResource.getSystemBuckets().empty()) { + // {system_buckets: ""} - match any system buckets in any db + resource = ResourcePattern::forAnySystemBuckets(); + } else { + // {system_buckets: "<coll>"} - match any system.buckets.<coll> in any db + resource = ResourcePattern::forAnySystemBucketsInAnyDatabase( + parsedResource.getSystemBuckets()); + } + } + } else { if (parsedResource.isDbSet() && !parsedResource.getDb().empty()) { if (parsedResource.isCollectionSet() && !parsedResource.getCollection().empty()) { @@ -458,6 +536,16 @@ bool ParsedPrivilege::privilegeToParsedPrivilege(const Privilege& privilege, parsedResource.setCollection(""); } else if (privilege.getResourcePattern().isClusterResourcePattern()) { parsedResource.setCluster(true); + } else if (privilege.getResourcePattern().isAnySystemBucketsCollection()) { + parsedResource.setSystemBuckets(""); + } else if (privilege.getResourcePattern().isAnySystemBucketsCollectionInDB()) { + parsedResource.setSystemBuckets(""); + parsedResource.setDb(privilege.getResourcePattern().databaseToMatch()); + } else if (privilege.getResourcePattern().isAnySystemBucketsCollectionInAnyDB()) { + parsedResource.setSystemBuckets(privilege.getResourcePattern().collectionToMatch()); + } else if (privilege.getResourcePattern().isExactSystemBucketsCollection()) { + parsedResource.setDb(privilege.getResourcePattern().databaseToMatch()); + parsedResource.setSystemBuckets(privilege.getResourcePattern().collectionToMatch()); } else if (privilege.getResourcePattern().isAnyResourcePattern()) { parsedResource.setAnyResource(true); } else { |