@okta/stormpath-migration
Version:
Migration tool to import Stormpath data into an Okta tenant
128 lines (118 loc) • 4.05 kB
JavaScript
/*!
* 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 logger = require('../util/logger');
const rs = require('../util/request-scheduler');
const ApiError = require('../util/api-error');
const POLICY_PATH = '/api/v1/policies';
// Cache the existing password policies since the list policies endpoint does
// now allow for filtering by name.
let passwordPolicies;
async function createDefaultRule(policy) {
logger.verbose(`Trying to create default rule for password policy id=${policy.id}`);
const url = `${POLICY_PATH}/${policy.id}/rules`;
const existing = await rs.get(url);
if (existing.length > 0) {
logger.exists(`Found default rule for password policy id=${policy.id}`);
return;
}
const created = await rs.post({
url,
body: {
type: 'PASSWORD',
name: 'Default Rule',
conditions: {
network: {
connection: 'ANYWHERE'
}
},
actions: {
passwordChange: {
access: 'ALLOW'
},
selfServicePasswordReset: {
access: 'ALLOW'
},
selfServiceUnlock: {
access: 'ALLOW'
}
}
}
});
logger.created(`Password policy rule id=${created.id} name=${created.name}`);
}
function getPolicyJson(groupId, policy) {
const json = {
type: 'PASSWORD',
conditions: {
people: {
groups: {
include: [groupId]
}
}
}
};
Object.assign(json, policy);
return json;
}
async function getPasswordPolicy(name) {
logger.verbose(`Getting existing passwordPolicy name=${name}`);
if (!passwordPolicies) {
logger.verbose('Getting and caching all existing password policies');
try {
const policies = await rs.get(`${POLICY_PATH}?type=PASSWORD`);
passwordPolicies = {};
for (let policy of policies) {
passwordPolicies[policy.name] = policy;
}
} catch (err) {
throw new ApiError(`Failed to get existing password policies name=${name}`, err);
}
}
return passwordPolicies[name];
}
async function updatePasswordPolicy(existing, groupId, policy) {
logger.verbose(`Updating existing password policy with name=${policy.name} id=${existing.id}`);
try {
Object.assign(existing, getPolicyJson(groupId, policy));
const updated = await rs.put({
url: `${POLICY_PATH}/${existing.id}`,
body: existing
});
logger.updated(`Password policy id=${updated.id}`);
await createDefaultRule(updated);
return updated;
} catch (err) {
throw new ApiError(`Failed to update password policy id=${existing.id}`, err);
}
}
async function createNewPasswordPolicy(groupId, policy) {
logger.verbose(`Creating password policy name=${policy.name} for groupId=${groupId}`);
try {
const created = await rs.post({
url: POLICY_PATH,
body: getPolicyJson(groupId, policy)
});
logger.created(`Password policy id=${created.id} name=${created.name}`);
await createDefaultRule(created);
return created;
} catch (err) {
throw new ApiError(`Failed to create password policy name=${policy.name}`, err);
}
}
async function createGroupPasswordPolicy(groupId, policy) {
logger.verbose(`Trying to create password policy name=${policy.name} for groupId=${groupId}`);
const existing = await getPasswordPolicy(policy.name);
return existing
? updatePasswordPolicy(existing, groupId, policy)
: createNewPasswordPolicy(groupId, policy);
}
module.exports = createGroupPasswordPolicy;