UNPKG

deep-package-manager

Version:
342 lines (277 loc) 9.04 kB
/** * Created by AlexanderC on 5/27/15. */ 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.IAMService = undefined; var _AbstractService = require('./AbstractService'); var _deepCore = require('deep-core'); var _deepCore2 = _interopRequireDefault(_deepCore); var _Exception = require('../../Exception/Exception'); var _FailedToCreateOIDCException = require('./Exception/FailedToCreateOIDCException'); var _FailedToDeleteOIDCException = require('./Exception/FailedToDeleteOIDCException'); var _FailedToGetOIDCProviderException = require('./Exception/FailedToGetOIDCProviderException'); var _FailedToAddClientIdToOIDCProviderException = require('./Exception/FailedToAddClientIdToOIDCProviderException'); var _url = require('url'); var _url2 = _interopRequireDefault(_url); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * IAM service */ class IAMService extends _AbstractService.AbstractService { /** * @param {Array} args */ constructor(...args) { super(...args); } /** * @returns {String} */ name() { return _deepCore2.default.AWS.Service.IDENTITY_AND_ACCESS_MANAGEMENT; } /** * @returns {String} */ static get OIDC_PROVIDER_APP_PREFIX() { return 'deep_app_'; } /** * @param {String} baseHash * @returns {String} */ static getDeepAppOIDCAudience(baseHash) { return `${IAMService.OIDC_PROVIDER_APP_PREFIX}${baseHash}`; } /** * @returns {String[]} */ static get AVAILABLE_REGIONS() { return [_deepCore2.default.AWS.Region.ANY]; } /** * @param {String} clientId * @returns {boolean} */ static isFakeOIDCProviderAudience(clientId) { let regExp = new RegExp(`^${IAMService.OIDC_PROVIDER_APP_PREFIX}.+$`); return regExp.test(clientId); } /** * @param {Core.Generic.ObjectStorage} services * @returns {IAMService} */ _setup(services) { let auth0Config = this.property.config.globals.auth0 || {}; let auth0Thumbprint = auth0Config.init && auth0Config.init.thumbprint ? auth0Config.init.thumbprint : null; if (this._isUpdate) { this._ready = true; return this; } var provisionDoneCb = response => { if (response) { response.domain = auth0Config.init.domain; response.clientID = auth0Config.init.clientID; } this._config.identityProvider = response; this._ready = true; }; if (auth0Thumbprint) { let oidcProviderArn = this._generateOIDCProviderArn(auth0Config.init.domain); this._checkOpenIDConnectProviderExists(oidcProviderArn, response => { if (response && response.ClientIDList) { response.OpenIDConnectProviderArn = oidcProviderArn; // adding a 'fake' audience used to manage OIDC provider undeploy let newClients = [IAMService.getDeepAppOIDCAudience(this.property.configObj.baseHash)]; if (response.ClientIDList.indexOf(auth0Config.init.clientID) === -1) { newClients.push(auth0Config.init.clientID); } this._addClientIDsToOpenIDConnectProvider(newClients, oidcProviderArn, () => { response.ClientIDList.concat(newClients); provisionDoneCb(response); }); } else { this._createOpenIDConnectProvider(auth0Config.init, provisionDoneCb); } }); } else { this._ready = true; } return this; } /** * @param {Core.Generic.ObjectStorage} services * @returns {IAMService} */ _postProvision(services) { // @todo: implement! if (this._isUpdate) { this._readyTeardown = true; return this; } this._readyTeardown = true; return this; } /** * @param {Core.Generic.ObjectStorage} services * @returns {IAMService} */ _postDeployProvision(services) { // @todo: implement! if (this._isUpdate) { this._ready = true; return this; } this._ready = true; return this; } /** * @param {Object} oidcProviderArn * @param {Function} callback * @private */ _checkOpenIDConnectProviderExists(oidcProviderArn, callback) { let iam = this.provisioning.iam; let params = { OpenIDConnectProviderArn: oidcProviderArn }; iam.getOpenIDConnectProvider(params, (error, data) => { if (error) { if (error.name === 'NoSuchEntity') { callback(null); } else { throw new _FailedToGetOIDCProviderException.FailedToGetOIDCProviderException(oidcProviderArn, error); } } else { callback(data); } }); } /** * @param {Array} clientIds * @param {String} oidcProviderArn * @param {Function} callback * @private */ _addClientIDsToOpenIDConnectProvider(clientIds, oidcProviderArn, callback) { let iam = this.provisioning.iam; let responses = 0; let params = { OpenIDConnectProviderArn: oidcProviderArn }; clientIds.forEach(clientId => { params.ClientID = clientId; iam.addClientIDToOpenIDConnectProvider(params, (error, data) => { responses++; if (error) { throw new _FailedToAddClientIdToOIDCProviderException.FailedToAddClientIdToOIDCProviderException(params.ClientID, params.OpenIDConnectProviderArn, error); } if (responses === clientIds.length) { callback(); } }); }); } /** * @param {Object} IdPConfig * @param {Function} callback * @private */ _createOpenIDConnectProvider(IdPConfig, callback) { let iam = this.provisioning.iam; // make sure provider protocol is https // @see http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/IAM.html#createOpenIDConnectProvider-property let urlParts = _url2.default.parse(IdPConfig.domain); urlParts.protocol = 'https'; let oidcProvderUrl = _url2.default.format(urlParts); let params = { ThumbprintList: [IdPConfig.thumbprint], Url: oidcProvderUrl, ClientIDList: [IdPConfig.clientID, // adding a 'fake' audience used to manage OIDC provider undeploy IAMService.getDeepAppOIDCAudience(this.property.configObj.baseHash)] }; iam.createOpenIDConnectProvider(params, (error, data) => { if (error) { throw new _FailedToCreateOIDCException.FailedToCreateOIDCException(params, error); } else { if (data) { data.ClientIDList = params.ClientIDList; } callback(data); } }); } /** * @param {String} identityProviderARN * @param {Function} callback * @private */ _deleteOpenIDConnectProvider(identityProviderARN, callback) { let iam = this.provisioning.iam; let params = { OpenIDConnectProviderArn: identityProviderARN }; iam.deleteOpenIDConnectProvider(params, (error, data) => { if (error) { throw new _FailedToDeleteOIDCException.FailedToDeleteOIDCException(identityProviderARN, error); } else { callback(data); } }); } /** * @param {String} providerDomain * @returns {String} */ _generateOIDCProviderArn(providerDomain) { return `arn:aws:iam::${this.awsAccountId}:oidc-provider/${providerDomain}`; } /** * Creates IAM role assume policy for passed aws service * * @param {*} serviceIdentifiers * @returns {Core.AWS.IAM.Policy} */ static getAssumeRolePolicy(...serviceIdentifiers) { let rolePolicy = new _deepCore2.default.AWS.IAM.Policy(); serviceIdentifiers.forEach(serviceIdentifier => { if (!_deepCore2.default.AWS.Service.exists(serviceIdentifier)) { throw new _Exception.Exception(`Unknown service identifier "${serviceIdentifier}".`); } let statement = rolePolicy.statement.add(); statement.principal = { Service: _deepCore2.default.AWS.Service.identifier(serviceIdentifier) }; let action = statement.action.add(); action.service = _deepCore2.default.AWS.Service.SECURITY_TOKEN_SERVICE; action.action = 'AssumeRole'; }); return rolePolicy; } /** * @returns {Core.AWS.IAM.Statement} */ generateAllowAlterIamStatement() { let policy = new _deepCore2.default.AWS.IAM.Policy(); let statement = policy.statement.add(); IAMService.IAM_ALTER_ACTIONS.forEach(actionName => { statement.action.add(_deepCore2.default.AWS.Service.IDENTITY_AND_ACCESS_MANAGEMENT, actionName); }); ['policy', 'role'].forEach(resourceType => { statement.resource.add(_deepCore2.default.AWS.Service.IDENTITY_AND_ACCESS_MANAGEMENT, '', // IAM service doesn't have regions this.awsAccountId, `${resourceType}/${this._getGlobalResourceMask()}`); }); return statement; } /** * @returns {String[]} */ static get IAM_ALTER_ACTIONS() { return ['createRole', 'deleteRole', 'deleteRolePolicy', 'getRole', 'putRolePolicy', 'updateAssumeRolePolicy', 'listRolePolicies']; } } exports.IAMService = IAMService;