aws-iam-policy-tool
Version:
AWS IAM role/policy management cli tool
105 lines (104 loc) • 4 kB
JavaScript
;
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;