diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2020-01-13 20:38:27 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-03 17:26:42 +0000 |
commit | 2de3fecd52943c1e0eb554834dd0422cabf958cd (patch) | |
tree | deea52eec191bbbf4d3c82a505edd4f05cc89499 /src/mongo/util/net/ssl_parameters.cpp | |
parent | eee29e9ce82913f0713ec11a1246a2d9a9c8e713 (diff) | |
download | mongo-2de3fecd52943c1e0eb554834dd0422cabf958cd.tar.gz |
SERVER-44435 Allow selective whitelisting of X509 based role authorizations
(cherry picked from commit b99fbe5f80f4368e1916e1bfbf3d195276ace5c7)
create mode 100644 jstests/ssl/tlsCATrusts.js
create mode 100644 jstests/ssl/x509/root-and-trusted-ca.pem
create mode 100644 jstests/ssl/x509/trusted-client-testdb-roles.pem
create mode 100644 src/mongo/db/auth/auth_types.idl
create mode 100644 src/mongo/util/net/ssl_parameters.idl
Diffstat (limited to 'src/mongo/util/net/ssl_parameters.cpp')
-rw-r--r-- | src/mongo/util/net/ssl_parameters.cpp | 108 |
1 files changed, 107 insertions, 1 deletions
diff --git a/src/mongo/util/net/ssl_parameters.cpp b/src/mongo/util/net/ssl_parameters.cpp index c15af3f9e59..27475d3ae34 100644 --- a/src/mongo/util/net/ssl_parameters.cpp +++ b/src/mongo/util/net/ssl_parameters.cpp @@ -30,6 +30,7 @@ #include "mongo/platform/basic.h" +#include "mongo/bson/json.h" #include "mongo/config.h" #include "mongo/db/auth/internal_user_auth.h" #include "mongo/db/auth/sasl_command_constants.h" @@ -37,6 +38,7 @@ #include "mongo/db/server_parameters.h" #include "mongo/util/net/ssl_manager.h" #include "mongo/util/net/ssl_options.h" +#include "mongo/util/net/ssl_parameters_gen.h" namespace mongo { @@ -196,6 +198,110 @@ public: } } clusterAuthModeSetting; -} // namespace +class TLSCATrustsSetParameter : public ServerParameter { +public: + TLSCATrustsSetParameter() + : ServerParameter(ServerParameterSet::getGlobal(), + "tlsCATrusts", + true, // allowedToChangeAtStartup + false // allowedToChangeAtRuntime + ) {} + + void append(OperationContext*, BSONObjBuilder&, const std::string&) final; + Status set(const BSONElement&) final; + Status setFromString(const std::string&) final; +} tlsCATrustsSetParameter; + +void TLSCATrustsSetParameter::append(OperationContext*, + BSONObjBuilder& b, + const std::string& name) { + if (!sslGlobalParams.tlsCATrusts) { + b.appendNull(name); + return; + } + + BSONArrayBuilder trusts; + + for (const auto& cait : sslGlobalParams.tlsCATrusts.get()) { + BSONArrayBuilder roles; + for (const auto& rolename : cait.second) { + BSONObjBuilder role; + role.append("role", rolename.getRole()); + role.append("db", rolename.getDB()); + roles.append(role.obj()); + } + + BSONObjBuilder ca; + ca.append("sha256", cait.first.toHexString()); + ca.append("roles", roles.arr()); + + trusts.append(ca.obj()); + } + + b.append(name, trusts.arr()); +} + +/** + * tlsCATrusts takes the form of an array of documents describing + * a set of roles which a given certificate authority may grant. + * + * [ + * { + * "sha256": "0123456789abcdef...", // SHA256 digest of a CA, as hex. + * "roles": [ // Array of grantable RoleNames + * { role: "read", db: "foo" }, + * { role: "readWrite", "db: "bar" }, + * // etc... + * ], + * }, + * // { "sha256": "...", roles: [...]}, // Additional documents... + * ] + * + * If this list has been set, and a client connects with a certificate + * containing roles which it has not been authorized to grant, + * then the connection will be refused. + * + * Wilcard roles may be defined by omitting the role and/or db portions: + * + * { role: "", db: "foo" } // May grant any role on the 'foo' DB. + * { role: "read", db: "" } // May grant 'read' role on any DB. + * { role: "", db: "" } // May grant any role on any DB. + */ +Status TLSCATrustsSetParameter::set(const BSONElement& element) try { + if ((element.type() != Object) || !element.Obj().couldBeArray()) { + return {ErrorCodes::BadValue, "Value must be an array"}; + } + + SSLParams::TLSCATrusts trusts; + for (const auto& trustElement : BSONArray(element.Obj())) { + if (trustElement.type() != Object) { + return {ErrorCodes::BadValue, "Value must be an array of trust definitions"}; + } + + IDLParserErrorContext ctx("tlsCATrusts"); + auto trust = TLSCATrust::parse(ctx, trustElement.Obj()); + + if (trusts.find(trust.getSha256()) != trusts.end()) { + return {ErrorCodes::BadValue, + str::stream() << "Duplicate thumbprint: " << trust.getSha256().toString()}; + } + + const auto& roles = trust.getRoles(); + trusts[std::move(trust.getSha256())] = std::set<RoleName>(roles.begin(), roles.end()); + } + + sslGlobalParams.tlsCATrusts = std::move(trusts); + return Status::OK(); +} catch (...) { + return exceptionToStatus(); +} + +Status TLSCATrustsSetParameter::setFromString(const std::string& json) try { + return set(BSON("" << fromjson(json)).firstElement()); +} catch (...) { + return exceptionToStatus(); +} + +} // namespace } // namespace mongo |