UNPKG

@okta/stormpath-migration

Version:

Migration tool to import Stormpath data into an Okta tenant

113 lines (101 loc) 4.32 kB
/*! * Copyright (c) 2017, Okta, Inc. and/or its affiliates. All rights reserved. * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (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. */ const Promise = require('bluebird'); const createOAuthClient = require('../functions/create-oauth-client'); const createAuthorizationServer = require('../functions/create-authorization-server'); const addAuthorizationServerToOAuthClient = require('../functions/add-authorization-server-to-oauth-client'); const createDefaultResourceAccessPolicy = require('../functions/create-default-resource-access-policy'); const stormpathExport = require('../stormpath/stormpath-export'); const logger = require('../util/logger'); const allSettled = require('../util/all-settled'); const config = require('../util/config'); const addGroupsToApp = require('../functions/add-groups-to-app'); const cache = require('./util/cache'); function getAppIdFromClient(client) { const parts = client._links.app.href.split('/'); return parts[parts.length - 1]; } async function getAccountStoreMap() { const mappings = await stormpathExport.getAccountStoreMappings(); logger.info(`Processing ${mappings.length} account store mappings`); return mappings.mapToObject((mapping, map) => { let oktaGroupId; const type = mapping.accountStoreType; const id = mapping.accountStoreId; switch (type) { case 'groups': oktaGroupId = cache.groupMap[id]; break; case 'organizations': oktaGroupId = cache.organizationMap[id]; break; case 'directories': oktaGroupId = cache.directoryMap[id]; break; default: throw new Error(`Unknown account store mapping type: ${type}`); } const appId = mapping.application.id; if (!map[appId]) { map[appId] = []; } if (!oktaGroupId) { logger.error(`No Okta group for Stormpath accountStoreMappingId=${mapping.id}`); } else { map[appId].push(oktaGroupId); } }, { limit: config.concurrencyLimit }); } async function addGroupsToApplication(application, client) { const appInstanceId = client.client_id ? client.client_id : getAppIdFromClient(client); const groupIds = cache.accountStoreMap[application.id]; if (!groupIds || groupIds.length === 0) { return logger.error('No Okta groups found to assign to application'); } logger.info(`Adding application id=${appInstanceId} to ${groupIds.length} groups`); return addGroupsToApp(appInstanceId, groupIds); } async function migrateApplication(application) { const lg = logger.group(`Stormpath application id=${application.id} name=${application.name}`); try { const name = `app:${application.name}`; const description = `Imported from Stormpath application id=${application.id}`; const [client, as] = await allSettled([ createOAuthClient(name), createAuthorizationServer(name, description, application.href) ]); await addGroupsToApplication(application, client); await allSettled([ createDefaultResourceAccessPolicy(as, client, application.tokenLimits), addAuthorizationServerToOAuthClient(as, client) ]); } catch (err) { logger.error(err); if (err.message.includes('Maximum number of instances has been reached')) { throw new Error('Reached maximum number of OAuth applications - contact support to raise this limit'); } } finally { lg.end(); } } async function migrateApplications() { logger.header('Starting applications import'); cache.accountStoreMap = await getAccountStoreMap(); const applications = await stormpathExport.getApplications(); logger.info(`Importing ${applications.length} applications`); try { await applications.each(migrateApplication, { limit: 1 }); } catch (err) { logger.error(`Failed to import all applications: ${err.message}`); } } module.exports = migrateApplications;