summaryrefslogtreecommitdiff
path: root/src/mongo/util/net/ssl_parameters.cpp
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2020-01-13 20:38:27 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-03 17:26:42 +0000
commit2de3fecd52943c1e0eb554834dd0422cabf958cd (patch)
treedeea52eec191bbbf4d3c82a505edd4f05cc89499 /src/mongo/util/net/ssl_parameters.cpp
parenteee29e9ce82913f0713ec11a1246a2d9a9c8e713 (diff)
downloadmongo-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.cpp108
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