Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / src / credentials.js
diff --git a/legacy-libs/grpc/src/credentials.js b/legacy-libs/grpc/src/credentials.js
new file mode 100644 (file)
index 0000000..9542acf
--- /dev/null
@@ -0,0 +1,276 @@
+/**
+ * @license
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * Credentials module
+ *
+ * This module contains factory methods for two different credential types:
+ * CallCredentials and ChannelCredentials. ChannelCredentials are things like
+ * SSL credentials that can be used to secure a connection, and are used to
+ * construct a Client object. CallCredentials genrally modify metadata, so they
+ * can be attached to an individual method call.
+ *
+ * CallCredentials can be composed with other CallCredentials to create
+ * CallCredentials. ChannelCredentials can be composed with CallCredentials
+ * to create ChannelCredentials. No combined credential can have more than
+ * one ChannelCredentials.
+ *
+ * For example, to create a client secured with SSL that uses Google
+ * default application credentials to authenticate:
+ *
+ * @example
+ * var channel_creds = credentials.createSsl(root_certs);
+ * (new GoogleAuth()).getApplicationDefault(function(err, credential) {
+ *   var call_creds = credentials.createFromGoogleCredential(credential);
+ *   var combined_creds = credentials.combineChannelCredentials(
+ *       channel_creds, call_creds);
+ *   var client = new Client(address, combined_creds);
+ * });
+ *
+ * @namespace grpc.credentials
+ */
+
+'use strict';
+
+var grpc = require('./grpc_extension');
+
+/**
+ * This cannot be constructed directly. Instead, instances of this class should
+ * be created using the factory functions in {@link grpc.credentials}
+ * @constructor grpc.credentials~CallCredentials
+ */
+var CallCredentials = grpc.CallCredentials;
+
+/**
+ * This cannot be constructed directly. Instead, instances of this class should
+ * be created using the factory functions in {@link grpc.credentials}
+ * @constructor grpc.credentials~ChannelCredentials
+ */
+var ChannelCredentials = grpc.ChannelCredentials;
+
+var Metadata = require('./metadata.js');
+
+var common = require('./common.js');
+
+var constants = require('./constants');
+
+/**
+ * @external GoogleCredential
+ * @see https://github.com/google/google-auth-library-nodejs
+ */
+
+const PEM_CERT_HEADER = "-----BEGIN CERTIFICATE-----";
+const PEM_CERT_FOOTER = "-----END CERTIFICATE-----";
+
+function wrapCheckServerIdentityCallback(callback) {
+  return function(hostname, cert) {
+    // Parse cert from pem to a version that matches the tls.checkServerIdentity
+    // format.
+    // https://nodejs.org/api/tls.html#tls_tls_checkserveridentity_hostname_cert
+
+    var pemHeaderIndex = cert.indexOf(PEM_CERT_HEADER);
+    if (pemHeaderIndex === -1) {
+      return new Error("Unable to parse certificate PEM.");
+    }
+    cert = cert.substring(pemHeaderIndex);
+    var pemFooterIndex = cert.indexOf(PEM_CERT_FOOTER);
+    if (pemFooterIndex === -1) {
+      return new Error("Unable to parse certificate PEM.");
+    }
+    cert = cert.substring(PEM_CERT_HEADER.length, pemFooterIndex);
+    var rawBuffer = Buffer.from(cert.replace("\n", "").replace(" ", ""), "base64");
+
+    return callback(hostname, { raw: rawBuffer });
+  }
+}
+
+/**
+ * Create an SSL Credentials object. If using a client-side certificate, both
+ * the second and third arguments must be passed. Additional peer verification
+ * options can be passed in the fourth argument as described below.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createSsl
+ * @kind function
+ * @param {Buffer=} root_certs The root certificate data
+ * @param {Buffer=} private_key The client certificate private key, if
+ *     applicable
+ * @param {Buffer=} cert_chain The client certificate cert chain, if applicable
+ * @param {Function} verify_options.checkServerIdentity Optional callback
+ *     receiving the expected hostname and peer certificate for additional
+ *     verification. The callback should return an Error if verification
+ *     fails and otherwise return undefined.
+ * @return {grpc.credentials~ChannelCredentials} The SSL Credentials object
+ */
+exports.createSsl = function(root_certs, private_key, cert_chain, verify_options) {
+  // The checkServerIdentity callback from gRPC core will receive the cert as a PEM.
+  // To better match the checkServerIdentity callback of Node, we wrap the callback
+  // to decode the PEM and populate a cert object.
+  if (verify_options && verify_options.checkServerIdentity) {
+    if (typeof verify_options.checkServerIdentity !== 'function') {
+      throw new TypeError("Value of checkServerIdentity must be a function.");
+    }
+    // Make a shallow clone of verify_options so our modification of the callback
+    // isn't reflected to the caller
+    var updated_verify_options = Object.assign({}, verify_options);
+    updated_verify_options.checkServerIdentity = wrapCheckServerIdentityCallback(
+        verify_options.checkServerIdentity);
+    arguments[3] = updated_verify_options;
+  }
+  return ChannelCredentials.createSsl.apply(this, arguments);
+}
+
+
+/**
+ * @callback grpc.credentials~metadataCallback
+ * @param {Error} error The error, if getting metadata failed
+ * @param {grpc.Metadata} metadata The metadata
+ */
+
+/**
+ * @callback grpc.credentials~generateMetadata
+ * @param {Object} params Parameters that can modify metadata generation
+ * @param {string} params.service_url The URL of the service that the call is
+ *     going to
+ * @param {grpc.credentials~metadataCallback} callback
+ */
+
+/**
+ * Create a gRPC credentials object from a metadata generation function. This
+ * function gets the service URL and a callback as parameters. The error
+ * passed to the callback can optionally have a 'code' value attached to it,
+ * which corresponds to a status code that this library uses.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createFromMetadataGenerator
+ * @param {grpc.credentials~generateMetadata} metadata_generator The function
+ *     that generates metadata
+ * @return {grpc.credentials~CallCredentials} The credentials object
+ */
+exports.createFromMetadataGenerator = function(metadata_generator) {
+  return CallCredentials.createFromPlugin(function(service_url, cb_data,
+                                                   callback) {
+    metadata_generator({service_url: service_url}, function(error, metadata) {
+      var code = constants.status.OK;
+      var message = '';
+      if (error) {
+        message = error.message;
+        if (error.hasOwnProperty('code') && Number.isFinite(error.code)) {
+          code = error.code;
+        } else {
+          code = constants.status.UNAUTHENTICATED;
+        }
+        if (!metadata) {
+          metadata = new Metadata();
+        }
+      }
+      callback(code, message, metadata._getCoreRepresentation(), cb_data);
+    });
+  });
+};
+
+function getAuthorizationHeaderFromGoogleCredential(google_credential, url, callback) {
+  // google-auth-library pre-v2.0.0 does not have getRequestHeaders
+  // but has getRequestMetadata, which is deprecated in v2.0.0
+  if (typeof google_credential.getRequestHeaders === 'function') {
+    google_credential.getRequestHeaders(url)
+      .then(function(header) {
+        callback(null, header.Authorization);
+      })
+      .catch(function(err) {
+        callback(err);
+        return;
+      });
+  } else {
+    google_credential.getRequestMetadata(url, function(err, header) {
+      if (err) {
+        callback(err);
+        return;
+      }
+      callback(null, header.Authorization);
+    });
+  }
+}
+
+/**
+ * Create a gRPC credential from a Google credential object.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createFromGoogleCredential
+ * @param {external:GoogleCredential} google_credential The Google credential
+ *     object to use
+ * @return {grpc.credentials~CallCredentials} The resulting credentials object
+ */
+exports.createFromGoogleCredential = function(google_credential) {
+  return exports.createFromMetadataGenerator(function(auth_context, callback) {
+    var service_url = auth_context.service_url;
+    getAuthorizationHeaderFromGoogleCredential(google_credential, service_url,
+      function(err, authHeader) {
+        if (err) {
+          common.log(constants.logVerbosity.INFO, 'Auth error:' + err);
+          callback(err);
+          return;
+        }
+        var metadata = new Metadata();
+        metadata.add('authorization', authHeader);
+        callback(null, metadata);
+      });
+  });
+};
+
+/**
+ * Combine a ChannelCredentials with any number of CallCredentials into a single
+ * ChannelCredentials object.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.combineChannelCredentials
+ * @param {grpc.credentials~ChannelCredentials} channel_credential The ChannelCredentials to
+ *     start with
+ * @param {...grpc.credentials~CallCredentials} credentials The CallCredentials to compose
+ * @return {grpc.credentials~ChannelCredentials} A credentials object that combines all of the
+ *     input credentials
+ */
+exports.combineChannelCredentials = function(channel_credential) {
+  var current = channel_credential;
+  for (var i = 1; i < arguments.length; i++) {
+    current = current.compose(arguments[i]);
+  }
+  return current;
+};
+
+/**
+ * Combine any number of CallCredentials into a single CallCredentials object
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.combineCallCredentials
+ * @param {...grpc.credentials~CallCredentials} credentials The CallCredentials to compose
+ * @return {grpc.credentials~CallCredentials} A credentials object that combines all of the input
+ *     credentials
+ */
+exports.combineCallCredentials = function() {
+  var current = arguments[0];
+  for (var i = 1; i < arguments.length; i++) {
+    current = current.compose(arguments[i]);
+  }
+  return current;
+};
+
+/**
+ * Create an insecure credentials object. This is used to create a channel that
+ * does not use SSL. This cannot be composed with anything.
+ * @memberof grpc.credentials
+ * @alias grpc.credentials.createInsecure
+ * @kind function
+ * @return {grpc.credentials~ChannelCredentials} The insecure credentials object
+ */
+exports.createInsecure = ChannelCredentials.createInsecure;