1 2 /** 3 * Copyright (C) 2018-present MongoDB, Inc. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the Server Side Public License, version 1, 7 * as published by MongoDB, Inc. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * Server Side Public License for more details. 13 * 14 * You should have received a copy of the Server Side Public License 15 * along with this program. If not, see 16 * <http://www.mongodb.com/licensing/server-side-public-license>. 17 * 18 * As a special exception, the copyright holders give permission to link the 19 * code of portions of this program with the OpenSSL library under certain 20 * conditions as described in each individual source file and distribute 21 * linked combinations including the program with the OpenSSL library. You 22 * must comply with the Server Side Public License in all respects for 23 * all of the code used other than as permitted herein. If you modify file(s) 24 * with this exception, you may extend this exception to your version of the 25 * file(s), but you are not obligated to do so. If you do not wish to do so, 26 * delete this exception statement from your version. If you delete this 27 * exception statement from all source files in the program, then also delete 28 * it in the license file. 29 */ 30 31 #pragma once 32 33 #include <iosfwd> 34 #include <string> 35 36 #include "mongo/base/string_data.h" 37 #include "mongo/db/namespace_string.h" 38 #include "mongo/platform/hash_namespace.h" 39 40 namespace mongo { 41 42 /** 43 * Representation of names of various kinds of resources targetable by the access control 44 * system. 45 * 46 * Three of the types of name, "forDatabaseName", "forExactNamespace" and "forClusterResource", 47 * can represent concrete resources targeted for manipulation by database operations. All of 48 * the types also act as patterns, useful for matching against groups of concrete resources as 49 * part of the access control system. See buildResourceSearchList() in 50 * authorization_session.cpp for details. 51 */ 52 class ResourcePattern { 53 public: 54 /** 55 * Returns a pattern that matches absolutely any resource. 56 */ forAnyResource()57 static ResourcePattern forAnyResource() { 58 return ResourcePattern(matchAnyResource); 59 } 60 61 /** 62 * Returns a pattern that matches any database or collection resource except collections for 63 * which ns.isSystem(). 64 */ forAnyNormalResource()65 static ResourcePattern forAnyNormalResource() { 66 return ResourcePattern(matchAnyNormalResource); 67 } 68 69 /** 70 * Returns a pattern that matches the "cluster" resource. 71 */ forClusterResource()72 static ResourcePattern forClusterResource() { 73 return ResourcePattern(matchClusterResource); 74 } 75 76 /** 77 * Returns a pattern that matches the named database, and NamespaceStrings 78 * "ns" for which ns.isSystem() is false and ns.db() == dbname. 79 */ forDatabaseName(StringData dbName)80 static ResourcePattern forDatabaseName(StringData dbName) { 81 return ResourcePattern(matchDatabaseName, NamespaceString(dbName, "")); 82 } 83 84 /** 85 * Returns a pattern that matches NamespaceStrings "ns" for which ns.coll() == 86 * collectionName. 87 */ forCollectionName(StringData collectionName)88 static ResourcePattern forCollectionName(StringData collectionName) { 89 return ResourcePattern(matchCollectionName, NamespaceString("", collectionName)); 90 } 91 92 /** 93 * Returns a pattern that matches the given exact namespace string. 94 */ forExactNamespace(const NamespaceString & ns)95 static ResourcePattern forExactNamespace(const NamespaceString& ns) { 96 return ResourcePattern(matchExactNamespace, ns); 97 } 98 99 /** 100 * Constructs a pattern that never matches. 101 */ ResourcePattern()102 ResourcePattern() : _matchType(matchNever) {} 103 104 /** 105 * Returns true if this pattern matches only exact namespaces. 106 */ isExactNamespacePattern()107 bool isExactNamespacePattern() const { 108 return _matchType == matchExactNamespace; 109 } 110 111 /** 112 * Returns true if this pattern matches on the database name only. 113 */ isDatabasePattern()114 bool isDatabasePattern() const { 115 return _matchType == matchDatabaseName; 116 } 117 118 /** 119 * Returns true if this pattern matches on the collection name only. 120 */ isCollectionPattern()121 bool isCollectionPattern() const { 122 return _matchType == matchCollectionName; 123 } 124 125 /** 126 * Returns true if this pattern matches the cluster resource only. 127 */ isClusterResourcePattern()128 bool isClusterResourcePattern() const { 129 return _matchType == matchClusterResource; 130 } 131 132 /** 133 * Returns true if this pattern matches only any normal resource. 134 */ isAnyNormalResourcePattern()135 bool isAnyNormalResourcePattern() const { 136 return _matchType == matchAnyNormalResource; 137 } 138 139 /** 140 * Returns true if this pattern matches any resource. 141 */ isAnyResourcePattern()142 bool isAnyResourcePattern() const { 143 return _matchType == matchAnyResource; 144 } 145 146 /** 147 * Returns the namespace that this pattern matches. 148 * 149 * Behavior is undefined unless isExactNamespacePattern() is true. 150 */ ns()151 const NamespaceString& ns() const { 152 return _ns; 153 } 154 155 /** 156 * Returns the database that this pattern matches. 157 * 158 * Behavior is undefined unless the pattern is of type matchDatabaseName or 159 * matchExactNamespace 160 */ databaseToMatch()161 StringData databaseToMatch() const { 162 return _ns.db(); 163 } 164 165 /** 166 * Returns the collection that this pattern matches. 167 * 168 * Behavior is undefined unless the pattern is of type matchCollectionName or 169 * matchExactNamespace 170 */ collectionToMatch()171 StringData collectionToMatch() const { 172 return _ns.coll(); 173 } 174 175 std::string toString() const; 176 hash()177 inline size_t hash() const { 178 // TODO: Choose a better hash function. 179 return MONGO_HASH_NAMESPACE::hash<std::string>()(_ns.ns()) ^ _matchType; 180 } 181 182 bool operator==(const ResourcePattern& other) const { 183 if (_matchType != other._matchType) 184 return false; 185 if (_ns != other._ns) 186 return false; 187 return true; 188 } 189 190 private: 191 enum MatchType { 192 matchNever = 0, /// Matches no resource. 193 matchClusterResource = 1, /// Matches if the resource is the cluster resource. 194 matchDatabaseName = 2, /// Matches if the resource's database name is _ns.db(). 195 matchCollectionName = 3, /// Matches if the resource's collection name is _ns.coll(). 196 matchExactNamespace = 4, /// Matches if the resource's namespace name is _ns. 197 matchAnyNormalResource = 5, /// Matches all databases and non-system collections. 198 matchAnyResource = 6 /// Matches absolutely anything. 199 }; 200 ResourcePattern(MatchType type)201 explicit ResourcePattern(MatchType type) : _matchType(type) {} ResourcePattern(MatchType type,const NamespaceString & ns)202 ResourcePattern(MatchType type, const NamespaceString& ns) : _matchType(type), _ns(ns) {} 203 204 MatchType _matchType; 205 NamespaceString _ns; 206 }; 207 208 std::ostream& operator<<(std::ostream& os, const ResourcePattern& pattern); 209 210 } // namespace mongo 211 212 MONGO_HASH_NAMESPACE_START 213 template <> 214 struct hash<mongo::ResourcePattern> { 215 size_t operator()(const mongo::ResourcePattern& resource) const { 216 return resource.hash(); 217 } 218 }; 219 MONGO_HASH_NAMESPACE_END 220