/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with this * work for additional information regarding copyright ownership. The ASF * licenses this file to you 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. */ var App = require('app'); /** @module utils.credentials **/ /** * Credential Resource format. * @typedef {object} credentialResourceObject * @property {string} principal user principal name * @property {string} key user password * @property {string} type type of credential store e.g. persistent or temporary */ module.exports = { STORE_TYPES: { TEMPORARY: 'temporary', PERSISTENT: 'persisted', PERSISTENT_KEY: 'persistent', TEMPORARY_KEY: 'temporary', PERSISTENT_PATH: 'storage.persistent', TEMPORARY_PATH: 'storage.temporary' }, ALIAS: { KDC_CREDENTIALS: 'kdc.admin.credential' }, /** * Store credentials to server * * @member utils.credentials * @param {string} clusterName cluster name * @param {string} alias credential alias name e.g. "kdc.admin.credentials" * @param {credentialResourceObject} resource resource info to set e.g. * * { * principal: "USERNAME", * key: "SecretKey", * type: "persisted" * } * * * Where: * * @returns {$.Deferred} promise object */ createCredentials: function(clusterName, alias, resource) { return App.ajax.send({ sender: this, name: 'credentials.create', data: { clusterName: clusterName, resource: resource, alias: alias }, error: 'createCredentialsErrorCallback' }); }, credentialsSuccessCallback: function(data, opt, params) { params.callback(data.items.length ? data.items.mapProperty('Credential') : []); }, createCredentialsErrorCallback: function(req, ajaxOpts, error) { }, /** * @see createCredentials * @member utils.credentials * @param {string} clusterName * @param {string} alias * @param {credentialResourceObject} resource * @returns {$.Deferred} promise object */ createOrUpdateCredentials: function(clusterName, alias, resource) { var self = this; var dfd = $.Deferred(); this.getCredential(clusterName, alias).then(function() { // update previously stored credentials self.updateCredentials(clusterName, alias, resource).always(function() { var status = arguments[1]; var result = arguments[2]; dfd.resolve(status === "success", result); }); }, function() { // create credentials if they not exist self.createCredentials(clusterName, alias, resource).always(function() { var status = arguments[1]; var result = arguments[2]; dfd.resolve(status === "success", result); }); }); return dfd.promise(); }, /** * Retrieve single credential from cluster by specified alias name * * @member utils.credentials * @param {string} clusterName cluster name * @param {string} alias credential alias name e.g. "kdc.admin.credentials" * @param {function} [callback] success callback to invoke, credential will be passed to first argument * @returns {$.Deferred} promise object */ getCredential: function(clusterName, alias, callback) { return App.ajax.send({ sender: this, name: 'credentials.get', data: { clusterName: clusterName, alias: alias, callback: callback }, success: 'getCredentialSuccessCallback', error: 'getCredentialErrorCallback' }); }, getCredentialSuccessCallback: function(data, opt, params) { if (params.callback) { params.callback(Em.getWithDefault(data, 'Credential', null)); } }, getCredentialErrorCallback: function() {}, /** * Update credential by alias and cluster name * * @see createCredentials * @param {string} clusterName * @param {string} alias * @param {object} resource * @returns {$.Deferred} promise object */ updateCredentials: function(clusterName, alias, resource) { return App.ajax.send({ sender: this, name: 'credentials.update', data: { clusterName: clusterName, alias: alias, resource: resource } }); }, /** * Get credenial list from server by specified cluster name * * @param {string} clusterName cluster name * @param {function} callback * @returns {$.Deferred} promise object */ credentials: function(clusterName, callback) { return App.ajax.send({ sender: this, name: 'credentials.list', data: { clusterName: clusterName, callback: callback }, success: 'credentialsSuccessCallback' }); }, /** * Remove credential from server by specified cluster name and alias * * @param {string} clusterName cluster name * @param {string} alias credential alias name e.g. "kdc.admin.credentials" */ removeCredentials: function(clusterName, alias) { return App.ajax.send({ sender: this, name: 'credentials.delete', data: { clusterName: clusterName, alias: alias } }); }, /** * Get info regarding credential storage type like persistent and temporary * * @param {string} clusterName cluster name * @param {function} callback * @returns {$.Deferred} promise object */ storageInfo: function(clusterName, callback) { return App.ajax.send({ sender: this, name: 'credentials.store.info', data: { clusterName: clusterName, callback: callback }, success: 'storageInfoSuccessCallback' }); }, storageInfoSuccessCallback: function(json, opt, params, request) { if (json.Clusters) { var storage = Em.getWithDefault(json, 'Clusters.credential_store_properties', {}); var storeTypesObject = {}; storeTypesObject[this.STORE_TYPES.PERSISTENT_KEY] = storage[this.STORE_TYPES.PERSISTENT_PATH] === "true"; storeTypesObject[this.STORE_TYPES.TEMPORARY_KEY] = storage[this.STORE_TYPES.TEMPORARY_PATH] === "true"; params.callback(storeTypesObject); } else { params.callback(null); } }, /** * Resolves promise with true value if secure store is persistent * * @param {string} clusterName * @returns {$.Deferred} promise object */ isStorePersisted: function(clusterName) { return this.storeTypeStatus(clusterName, this.STORE_TYPES.PERSISTENT_KEY); }, /** * Resolves promise with true value if secure store is temporary * * @param {string} clusterName * @returns {$.Deferred} promise object */ isStoreTemporary: function(clusterName) { return this.storeTypeStatus(clusterName, this.STORE_TYPES.TEMPORARY_KEY); }, /** * Get store type value for specified cluster and store type e.g. persistent or temporary * * @member utils.credentials * @param {string} clusterName * @param {string} type store type e.g. persistent or temporary * @returns {$.Deferred} promise object */ storeTypeStatus: function(clusterName, type) { var dfd = $.Deferred(); this.storageInfo(clusterName, function(storage) { dfd.resolve(Em.get(storage, type)); }).fail(function(error) { dfd.reject(error); }); return dfd.promise(); }, /** * Generate payload for storing credential. * * @member utils.credentials * @param {string} principal principal name * @param {string} key secret key * @param {string} type storage type e.g. persisted, temporary * @returns {credentialResourceObject} resource template */ createCredentialResource: function(principal, key, type) { return { principal: principal, key: key, type: type }; }, /** * Check that KDC credentials stored as persisted and not temporary from specified credentials list. * * @member utils.credentials * @param {object[]} credentials credentials list retrieved from API @see credentials * @returns {boolean} true if credentials are persisted */ isKDCCredentialsPersisted: function(credentials) { var kdcCredentials = credentials.findProperty('alias', this.ALIAS.KDC_CREDENTIALS); if (kdcCredentials) { return Em.getWithDefault(kdcCredentials, 'type', this.STORE_TYPES.TEMPORARY) === this.STORE_TYPES.PERSISTENT; } return false; } };