Skip to content

Commit

Permalink
implement X509 auth (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
hviana authored Jan 14, 2021
1 parent 4855e1b commit bc7aa64
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/auth/mod.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./base.ts";
export * from "./scram.ts";
export * from "./x509.ts";
2 changes: 1 addition & 1 deletion src/auth/scram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class ScramAuthPlugin extends AuthPlugin {
return request;
}

async auth(authContext: AuthContext) {
async auth(authContext: AuthContext): Promise<Document> {
const response = authContext.response;
if (response && response.speculativeAuthenticate) {
return await continueScramConversation(
Expand Down
43 changes: 43 additions & 0 deletions src/auth/x509.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Credential, Document } from "../types.ts";
import { AuthContext, AuthPlugin } from "./base.ts";
import { HandshakeDocument } from "../protocol/handshake.ts";
import { driverMetadata } from "../protocol/mod.ts";

export interface X509Command extends Document {
authenticate: number;
mechanism: string;
user?: string;
}

export class X509AuthPlugin extends AuthPlugin {
constructor() {
super();
}
prepare(authContext: AuthContext): Document {
const handshakeDoc = <HandshakeDocument> {
ismaster: true,
client: driverMetadata,
compression: authContext.options.compression,
speculativeAuthenticate: x509AuthenticateCommand(authContext.credentials),
};
return handshakeDoc;
}

async auth(authContext: AuthContext): Promise<Document> {
if (authContext.response!.speculativeAuthenticate) {
return authContext.response!;
}
return await authContext.protocol.commandSingle(
"$external",
x509AuthenticateCommand(authContext.credentials),
);
}
}

function x509AuthenticateCommand(credentials?: Credential): Document {
const command: X509Command = { authenticate: 1, mechanism: "MONGODB-X509" };
if (credentials) {
command.user = credentials!.username;
}
return command;
}
18 changes: 16 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ListDatabaseInfo,
} from "./types.ts";
import { parse } from "./utils/uri.ts";
import { AuthContext, ScramAuthPlugin } from "./auth/mod.ts";
import { AuthContext, ScramAuthPlugin, X509AuthPlugin } from "./auth/mod.ts";
import { MongoError } from "./error.ts";

const DENO_DRIVER_VERSION = "0.0.1";
Expand Down Expand Up @@ -36,6 +36,16 @@ export class MongoClient {
if (options.certFile) {
denoConnectOps.certFile = options.certFile;
}
if (options.keyFile) {
if (options.keyFilePassword) {
throw new MongoError(
`Tls keyFilePassword not implemented in Deno driver`,
);
//TODO, need something like const key = decrypt(options.keyFile) ...
}
throw new MongoError(`Tls keyFile not implemented in Deno driver`);
//TODO, need Deno.connectTls with something like key or keyFile option.
}
conn = await Deno.connectTls(denoConnectOps);
} else {
conn = await Deno.connect(denoConnectOps);
Expand All @@ -56,8 +66,12 @@ export class MongoClient {
authPlugin = new ScramAuthPlugin("sha256"); //TODO AJUST sha256
} else if (mechanism === "SCRAM-SHA-1") {
authPlugin = new ScramAuthPlugin("sha1");
} else if (mechanism === "MONGODB-X509") {
authPlugin = new X509AuthPlugin();
} else {
throw new MongoError(`Auth mechanism not implemented: ${mechanism}`);
throw new MongoError(
`Auth mechanism not implemented in Deno driver: ${mechanism}`,
);
}
const request = authPlugin.prepare(authContext);
authContext.response = await this.#protocol.commandSingle(
Expand Down
1 change: 1 addition & 0 deletions src/protocol/handshake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface HandshakeDocument extends Document {
client: any;
compression: string[];
saslSupportedMechs?: string;
speculativeAuthenticate?: Document;
}

interface HandshakeResponse {
Expand Down
4 changes: 3 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export type Document = Bson.Document;
export interface ConnectOptions {
compression?: string[];
certFile?: string;
keyFile?: string;
keyFilePassword?: string;
tls?: boolean;
safe?: boolean;
credential?: Credential;
Expand Down Expand Up @@ -341,7 +343,7 @@ export interface Credential {
/**
* Which authentication mechanism to use. If not provided, one will be negotiated with the server.
*/
mechanism?: "SCRAM-SHA-1" | "SCRAM-SHA-256";
mechanism?: "SCRAM-SHA-1" | "SCRAM-SHA-256" | "MONGODB-X509";
}

export interface IndexOptions {
Expand Down
10 changes: 8 additions & 2 deletions src/utils/uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { ConnectOptions, Credential } from "../types.ts";

interface Parts {
auth?: { user: string; password: string };
auth?: { user: string; password?: string };
hash?: any;
hostname?: string;
href?: string;
Expand All @@ -25,7 +25,7 @@ export function parse_url(url: string): Parts {
"hash",
];
const pattern =
/([^:/?#]+:)?(?:(?:\/\/)(?:([^/?#]*:[^@/]+)@)?([^/:?#]+)(?:(?::)(\d+))?)?(\/?[^?#]*)?(\?[^#]*)?(#[^\s]*)?/;
/([^:/?#]+:)?(?:(?:\/\/)(?:([^/?#]*:?[^@/]+)@)?([^/:?#]+)(?:(?::)(\d+))?)?(\/?[^?#]*)?(\?[^#]*)?(#[^\s]*)?/;

function parse_simple(url: string): any {
const parts: any = {};
Expand Down Expand Up @@ -118,6 +118,12 @@ export function parse(url: string, optOverride: any = {}): ConnectOptions {
if (data.search.tlsCAFile) {
connectOptions.certFile = data.search.tlsCAFile;
}
if (data.search.tlsCertificateKeyFile) {
connectOptions.keyFile = data.search.tlsCertificateKeyFile;
}
if (data.search.tlsCertificateKeyFilePassword) {
connectOptions.keyFilePassword = data.search.tlsCertificateKeyFilePassword;
}
if (data.search.safe) {
connectOptions.safe = data.search.safe === "true";
}
Expand Down

0 comments on commit bc7aa64

Please sign in to comment.