Adding the possibility to connect with credentials over an insecure channel through a singleton having a metadata object containing the token

This commit is contained in:
Sebastien Ritz 2017-10-13 10:06:04 +02:00
Родитель 5434b6621c
Коммит cad614ae8c
2 изменённых файлов: 41 добавлений и 10 удалений

Просмотреть файл

@ -5,6 +5,7 @@ import { castGrpcError, GRPCGenericError } from './errors';
import { IOptions } from './options'; import { IOptions } from './options';
import { ICallable, Services } from './rpc'; import { ICallable, Services } from './rpc';
import { SharedPool } from './shared-pool'; import { SharedPool } from './shared-pool';
import { SimpleToken } from './simple-token';
import { forOwn } from './util'; import { forOwn } from './util';
const services = grpc.load(`${__dirname}/../proto/rpc.proto`); const services = grpc.load(`${__dirname}/../proto/rpc.proto`);
@ -30,8 +31,9 @@ function removeProtocolPrefix(name: string) {
* into a Promise. * into a Promise.
*/ */
function runServiceCall(client: grpc.Client, method: string, payload: object): Promise<any> { function runServiceCall(client: grpc.Client, method: string, payload: object): Promise<any> {
const metadata: grpc.Metadata = SimpleToken.Instance.metadata;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
(<any>client)[method](payload, (err: Error | null, res: any) => { (<any>client)[method](payload, metadata, (err: Error | null, res: any) => {
if (err) { if (err) {
reject(castGrpcError(err)); reject(castGrpcError(err));
} else { } else {
@ -80,10 +82,18 @@ class Authenticator {
return this.getCredentialsFromHost(host, auth.username, auth.password, original) return this.getCredentialsFromHost(host, auth.username, auth.password, original)
.then(token => { .then(token => {
this.awaitingToken = null; this.awaitingToken = null;
return grpc.credentials.combineChannelCredentials( try {
original, return grpc.credentials.combineChannelCredentials(
this.createMetadataAugmenter(token), original,
); this.createMetadataAugmenter(token),
);
} catch(e) {
// The the token in meta of the singleton
SimpleToken.Instance.setToken(token);
// If we have an insecure connection but a name/password auth, we just return the channel
return original;
}
}) })
.catch(err => attempt(index + 1, err)); .catch(err => attempt(index + 1, err));
}; };
@ -276,11 +286,6 @@ export class ConnectionPool implements ICallable {
); );
} else if (this.hasSecureHost()) { } else if (this.hasSecureHost()) {
protocolCredentials = grpc.credentials.createSsl(); protocolCredentials = grpc.credentials.createSsl();
} else if (this.options.auth) {
throw new Error(
'grpc does not allow you to use password authentication without connecting ' +
'over SSL. See how to set up etcd with ssl here: https://git.io/v7uhX',
);
} }
return this.authenticator.augmentCredentials(protocolCredentials); return this.authenticator.augmentCredentials(protocolCredentials);

26
src/simple-token.ts Normal file
Просмотреть файл

@ -0,0 +1,26 @@
import * as grpc from 'grpc';
export class SimpleToken {
private static _instance: SimpleToken;
public static get Instance() {
return this._instance || (this._instance = new this());
}
private _metadata: grpc.Metadata;
private constructor() {
this._metadata = new grpc.Metadata();
}
public get metadata(): grpc.Metadata {
return this._metadata;
}
public setToken(token: string) {
const meta = new grpc.Metadata();
meta.add('token', token);
this._metadata = meta;
}
}