@cloud-copilot/iam-policy
Version:
An ORM for AWS IAM policies
226 lines • 9.13 kB
JavaScript
import { ActionImpl } from '../actions/action.js';
import { ConditionImpl } from '../conditions/condition.js';
import { PrincipalImpl } from '../principals/principal.js';
import { ResourceImpl } from '../resources/resource.js';
/**
* Implementation of the Statement interface and all its sub-interfaces
*/
export class StatementImpl {
constructor(statementObject, _index, otherProps) {
this.statementObject = statementObject;
this._index = _index;
this.otherProps = otherProps;
}
index() {
return this._index;
}
path() {
return this.otherProps.path;
}
sid() {
return this.statementObject.Sid;
}
effect() {
return this.statementObject.Effect;
}
isAllow() {
return this.effect() === 'Allow';
}
isDeny() {
return this.effect() === 'Deny';
}
isPrincipalStatement() {
return this.statementObject.Principal !== undefined;
}
isNotPrincipalStatement() {
return this.statementObject.NotPrincipal !== undefined;
}
principals() {
if (!this.isPrincipalStatement()) {
throw new Error('Called principals on a statement without Principal, use isPrincipalStatement before calling principals');
}
return this.parsePrincipalObject(this.statementObject.Principal);
}
principalTypeIsArray(principalType) {
if (!this.isPrincipalStatement()) {
throw new Error('Called principalTypeIsArray on a statement without Principal, use isPrincipalStatement before calling principalTypeIsArray');
}
return (typeof this.statementObject.Principal === 'object' &&
Array.isArray(this.statementObject.Principal[principalType]));
}
hasSingleWildcardPrincipal() {
if (!this.isPrincipalStatement()) {
throw new Error('Called hasSingleWildcardPrincipal on a statement without Principal, use isPrincipalStatement before calling hasSingleWildcardPrincipal');
}
return this.statementObject.Principal === '*';
}
notPrincipals() {
if (!this.isNotPrincipalStatement()) {
throw new Error('Called notPrincipals on a statement without NotPrincipal, use isNotPrincipalStatement before calling notPrincipals');
}
return this.parsePrincipalObject(this.statementObject.NotPrincipal);
}
notPrincipalTypeIsArray(notPrincipalType) {
if (!this.isNotPrincipalStatement()) {
throw new Error('Called notPrincipalTypeIsArray on a statement without NotPrincipal, use isNotPrincipalStatement before calling notPrincipalTypeIsArray');
}
return (typeof this.statementObject.NotPrincipal === 'object' &&
Array.isArray(this.statementObject.NotPrincipal[notPrincipalType]));
}
hasSingleWildcardNotPrincipal() {
if (!this.isNotPrincipalStatement()) {
throw new Error('Called hasSingleWildcardNotPrincipal on a statement without NotPrincipal, use isNotPrincipalStatement before calling hasSingleWildcardNotPrincipal');
}
return this.statementObject.NotPrincipal === '*';
}
/**
* Parse the principal object into PrincipalImpl objects.
*
* This is non trivial and we don't want to implement this in each function.
*
* @param principals the Principal or NotPrincipal object ot parse
* @returns the backing principals for a Principal or NotPrincipal object
*/
parsePrincipalObject(principals) {
if (typeof principals === 'string') {
return [new PrincipalImpl('AWS', principals)];
}
return Object.entries(principals)
.map(([principalType, principalValue]) => {
if (typeof principalValue === 'string') {
return new PrincipalImpl(principalType, principalValue);
}
return Object.entries(principalValue).map(([key, value]) => {
return new PrincipalImpl(principalType, value);
});
})
.flat();
}
isActionStatement() {
return this.statementObject.Action !== undefined;
}
isNotActionStatement() {
return this.statementObject.NotAction !== undefined;
}
actions() {
if (!this.isActionStatement()) {
throw new Error('Called actions on a statement without Action, use isActionStatement before calling actions');
}
return this.createNewActions();
}
createNewActions() {
if (!this.actionIsArray()) {
return [new ActionImpl(this.statementObject.Action, { path: `${this.path()}.Action` })];
}
return [this.statementObject.Action].flat().map((action, index) => {
return new ActionImpl(action, { path: `${this.path()}.Action[${index}]` });
});
}
actionIsArray() {
return Array.isArray(this.statementObject.Action);
}
notActions() {
if (!this.isNotActionStatement()) {
throw new Error('Called notActions on a statement without NotAction, use isNotActionStatement before calling notActions');
}
return this.createNewNotActions();
}
createNewNotActions() {
if (!this.notActionIsArray()) {
return [new ActionImpl(this.statementObject.NotAction, { path: `${this.path()}.NotAction` })];
}
return [this.statementObject.NotAction].flat().map((action, index) => {
return new ActionImpl(action, { path: `${this.path()}.NotAction[${index}]` });
});
}
notActionIsArray() {
return Array.isArray(this.statementObject.NotAction);
}
isResourceStatement() {
return this.statementObject.Resource !== undefined;
}
isNotResourceStatement() {
return this.statementObject.NotResource !== undefined;
}
resources() {
if (!this.isResourceStatement()) {
throw new Error('Called resources on a statement without Resource, use isResourceStatement before calling resources');
}
return this.createNewResources();
}
createNewResources() {
if (!this.resourceIsArray()) {
return [new ResourceImpl(this.statementObject.Resource, { path: `${this.path()}.Resource` })];
}
return [this.statementObject.Resource].flat().map((resource, index) => {
return new ResourceImpl(resource, { path: `${this.path()}.Resource[${index}]` });
});
}
hasSingleResourceWildcard() {
if (!this.isResourceStatement()) {
throw new Error('Called hasSingleResourceWildcard on a statement without Resource, use isResourceStatement before calling hasSingleResourceWildcard');
}
return this.statementObject.Resource === '*';
}
resourceIsArray() {
return Array.isArray(this.statementObject.Resource);
}
notResources() {
if (!this.isNotResourceStatement()) {
throw new Error('Called notResources on a statement without NotResource, use isNotResourceStatement before calling notResources');
}
return this.createNewNotResources();
}
createNewNotResources() {
if (!this.notResourceIsArray()) {
return [
new ResourceImpl(this.statementObject.NotResource, { path: `${this.path()}.NotResource` })
];
}
return [this.statementObject.NotResource].flat().map((resource, index) => {
return new ResourceImpl(resource, { path: `${this.path()}.NotResource[${index}]` });
});
}
notResourceIsArray() {
return Array.isArray(this.statementObject.NotResource);
}
hasSingleNotResourceWildcard() {
if (!this.isNotResourceStatement()) {
throw new Error('Called hasSingleNotResourceWildcard on a statement without NotResource, use isNotResourceStatement before calling hasSingleNotResourceWildcard');
}
return this.statementObject.NotResource === '*';
}
conditionMap() {
if (!this.statementObject.Condition) {
return undefined;
}
const result = {};
for (const key of Object.keys(this.statementObject.Condition)) {
const value = this.statementObject.Condition[key];
result[key] = {};
for (const subKey of Object.keys(value)) {
const subValue = value[subKey];
result[key][subKey] = Array.isArray(subValue) ? subValue : [subValue];
}
}
return result;
}
conditions() {
return this.createNewConditions();
}
createNewConditions() {
if (!this.statementObject.Condition) {
return [];
}
return Object.entries(this.statementObject.Condition)
.map(([opKey, opValue]) => {
return Object.entries(opValue).map(([condKey, condValue]) => {
return new ConditionImpl(opKey, condKey, condValue, {
conditionPath: `${this.path()}.Condition`
});
});
})
.flat();
}
}
//# sourceMappingURL=statement.js.map