UNPKG

aws-iam-policy-tool

Version:
105 lines (104 loc) 4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const jsonDiff = require('json-diff'); const role_1 = require("../aws/role"); const attach_1 = require("../aws/attach"); const result_1 = require("../utils/result"); const operation_1 = require("../aws/operation"); class InvalidRoleError extends Error { constructor(msg, target, diff) { super(msg); this.target = target; this.diff = diff || null; } } exports.InvalidRoleError = InvalidRoleError; class RoleValidator { constructor(opts = {}) { this._color = !(opts['plain'] || false); this._invalidCnt = 0; } async validate(roleEntry) { const roleName = roleEntry.Role.RoleName; try { await this._validateRoleOrRoleWithInstanceProfile(roleEntry.Role); const results = await this._validatePolicies(roleName, roleEntry.AttachedPolicies); if (results.length) { this._invalidCnt++; return results; } return [result_1.OK(roleName)]; } catch (err) { if (err instanceof InvalidRoleError) { this._invalidCnt++; return [result_1.NG(err.message, err.target, err.diff)]; } return [result_1.NG('Role: %1 is invalid JSON format.', roleName)]; } } async _validateRoleOrRoleWithInstanceProfile(definedRole) { const currentRole = await this._getRoleOrRoleWithInstanceProfile(definedRole); const current = this._convertForDiff(currentRole); const defined = this._convertForDiff(definedRole); const df = jsonDiff.diffString(current, defined, { color: this._color }); if (df) { throw new InvalidRoleError('%1 is invalid.', definedRole.RoleName, df); } } async _getRoleOrRoleWithInstanceProfile(role) { const { RoleName: roleName, isEc2Role } = role; if (isEc2Role) { const profile = await operation_1.getInstanceProfile(roleName); if (!profile) { throw new InvalidRoleError('%1 instance profile does not exist.', roleName); } const { RoleName, Path, AssumeRolePolicyDocument } = profile.Roles[0]; return new role_1.RoleNode(RoleName, Path, AssumeRolePolicyDocument ? JSON.parse(decodeURIComponent(AssumeRolePolicyDocument)) : undefined); } else { const gotRole = await role_1.RoleNode.findRole(roleName); if (!gotRole) { throw new InvalidRoleError('%1 does not exist.', roleName); } return gotRole; } } async _validatePolicies(roleName, attachedPolicies) { const currentPolicies = await operation_1.getAttachedPoliciesByRole(roleName); const results = []; const definedPolicies = attachedPolicies; definedPolicies.forEach((definedPolicy) => { if (!attach_1.containPolicy(currentPolicies, definedPolicy)) { results.push(result_1.NG('Role: %1 does not have Policy: %2.', [ roleName, definedPolicy.PolicyName, ])); } }); currentPolicies.forEach((currentPolicy) => { if (!attach_1.containPolicy(definedPolicies, currentPolicy)) { results.push(result_1.NG('Role: %1 have Policy: %2 not required.', [ roleName, currentPolicy.PolicyName, ])); } }); return results; } isValid() { return this._invalidCnt === 0; } _convertForDiff(role) { const data = JSON.parse(JSON.stringify(role)); delete data.Arn; delete data.RoleId; delete data.CreateDate; delete data.MaxSessionDuration; delete data.Tags; return data; } } exports.RoleValidator = RoleValidator;