/** * Copyright (C) 2018-present MongoDB, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the Server Side Public License, version 1, * as published by MongoDB, Inc. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Server Side Public License for more details. * * You should have received a copy of the Server Side Public License * along with this program. If not, see * . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the Server Side Public License in all respects for * all of the code used other than as permitted herein. If you modify file(s) * with this exception, you may extend this exception to your version of the * file(s), but you are not obligated to do so. If you do not wish to do so, * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. */ #pragma once #include #include #include "mongo/db/auth/restriction.h" namespace mongo { namespace restriction_detail { // Represents a set of restrictions, which may be attached to a user or role. // This set of restrictions is met by a RestrictionEnvironment, if any restriction // in the set is met by the RestrictionEnvironment, or if the set is empty. template class Pointer = std::unique_ptr, template class Sequence = std::vector> class RestrictionSetAny : public UnnamedRestriction { public: using element_type = T; using pointer_type = Pointer; using sequence_type = Sequence; RestrictionSetAny() = default; explicit RestrictionSetAny(sequence_type restrictions) : _restrictions(std::move(restrictions)) {} template explicit RestrictionSetAny(std::unique_ptr restriction) { _restrictions.push_back(std::move(restriction)); } Status validate(const RestrictionEnvironment& environment) const final { if (_restrictions.empty()) { return Status::OK(); } for (const pointer_type& restriction : _restrictions) { Status status = restriction->validate(environment); if (status.isOK()) { return status; } } return Status(ErrorCodes::AuthenticationRestrictionUnmet, str::stream() << "No member restriction in '" << *this << "' met"); } void appendToBuilder(BSONArrayBuilder* builder) const final { builder->append(toBSON()); } typename T::serialization_type::bson_type toBSON() const { typename T::serialization_type::bson_builder_type builder; for (const auto& r : _restrictions) { r->appendToBuilder(&builder); } return T::serialization_type::finalize(&builder); } private: void serialize(std::ostream& os) const final { os << "{anyOf: ["; for (const pointer_type& restriction : _restrictions) { if (restriction.get() != _restrictions.front().get()) { os << ", "; } os << *restriction; } os << "]}"; } sequence_type _restrictions; }; // Represents a set of restrictions which may be attached to a user or role. This set of is met by // a RestrictionEnvironment, if each set is met by the RestrictionEnvironment. template class Pointer = std::unique_ptr, template class Sequence = std::vector> class RestrictionSetAll : public UnnamedRestriction { public: using element_type = T; using pointer_type = Pointer; using sequence_type = Sequence; RestrictionSetAll() = default; explicit RestrictionSetAll(sequence_type restrictions) : _restrictions(std::move(restrictions)) {} template explicit RestrictionSetAll(std::unique_ptr restriction) { _restrictions.push_back(std::move(restriction)); } explicit RestrictionSetAll(const T& restriction) { _restrictions.push_back(std::make_unique(restriction)); } Status validate(const RestrictionEnvironment& environment) const final { for (const pointer_type& restriction : _restrictions) { Status status = restriction->validate(environment); if (!status.isOK()) { return Status(ErrorCodes::AuthenticationRestrictionUnmet, str::stream() << "Restriction '" << *restriction << "' in '" << *this << "' unmet"); } } return Status::OK(); } void appendToBuilder(BSONArrayBuilder* builder) const final { builder->append(toBSON()); } typename T::serialization_type::bson_type toBSON() const { typename T::serialization_type::bson_builder_type builder; for (const auto& r : _restrictions) { r->appendToBuilder(&builder); } return T::serialization_type::finalize(&builder); } private: void serialize(std::ostream& os) const final { os << "{allOf: ["; for (const pointer_type& restriction : _restrictions) { if (restriction.get() != _restrictions.front().get()) { os << ", "; } os << *restriction; } os << "]}"; } sequence_type _restrictions; }; } // namespace restriction_detail // Users and roles may have a set of sets of restrictions. The set of set of restrictions is met if // any of the sets are met. The sets are met if all of their restrictions are met. // A user may have restrictions, and may have roles with restrictions. If it acquires multiple // sets of restrictions, then the user's restrictions, and each of their roles' restrictions must // be met. template