@cloud-copilot/iam-lens
Version:
Visibility in IAM in and across AWS accounts
121 lines • 5.1 kB
JavaScript
import { convertAssumedRoleArnToRoleArn, isAssumedRoleArn, isIamRoleArn, isIamUserArn, splitArnParts } from '@cloud-copilot/iam-utils';
import { IamCollectClient } from './collect/client.js';
/**
* Get all the IAM policies for a user, including managed and inline policies, permission boundaries, and group policies.
*
* @param collectClient the IAM collect client to use for retrieving policies
* @param principalArn the ARN of the user to get policies for
* @returns an object containing the managed policies, inline policies, permission boundary, and group policies
*/
export async function getAllPoliciesForUser(collectClient, principalArn) {
const accountId = splitArnParts(principalArn).accountId;
const managedPolicies = await collectClient.getManagedPoliciesForUser(principalArn);
const inlinePolicies = await collectClient.getInlinePoliciesForUser(principalArn);
const permissionBoundary = await collectClient.getPermissionsBoundaryForUser(principalArn);
const groups = await collectClient.getGroupsForUser(principalArn);
const scps = await collectClient.getScpHierarchyForAccount(accountId);
const rcps = await collectClient.getRcpHierarchyForAccount(accountId);
const groupPolicies = [];
for (const group of groups) {
const groupManagedPolicies = await collectClient.getManagedPoliciesForGroup(group);
const groupInlinePolicies = await collectClient.getInlinePoliciesForGroup(group);
groupPolicies.push({
group,
managedPolicies: groupManagedPolicies,
inlinePolicies: groupInlinePolicies
});
}
return {
scps,
rcps,
managedPolicies,
inlinePolicies,
permissionBoundary,
groupPolicies
};
}
/**
* Get all the IAM policies for a role, including managed and inline policies and permission boundaries.
*
* @param collectClient the IAM collect client to use for retrieving policies
* @param principalArn the ARN of the role to get policies for
* @returns an object containing the managed policies, inline policies, and permission boundary
*/
export async function getAllPoliciesForRole(collectClient, principalArn) {
const accountId = splitArnParts(principalArn).accountId;
const managedPolicies = await collectClient.getManagedPoliciesForRole(principalArn);
const inlinePolicies = await collectClient.getInlinePoliciesForRole(principalArn);
const permissionBoundary = await collectClient.getPermissionsBoundaryForRole(principalArn);
const scps = await collectClient.getScpHierarchyForAccount(accountId);
const rcps = await collectClient.getRcpHierarchyForAccount(accountId);
return {
scps,
rcps,
managedPolicies,
inlinePolicies,
permissionBoundary
};
}
export async function getAllPoliciesForPrincipal(collectClient, principalArn) {
if (isServicePrincipal(principalArn) ||
isSamlPrincipal(principalArn) ||
isOidcPrincipal(principalArn)) {
return {
scps: [],
rcps: [],
managedPolicies: [],
inlinePolicies: [],
permissionBoundary: undefined,
groupPolicies: []
};
}
if (isIamUserArn(principalArn)) {
return getAllPoliciesForUser(collectClient, principalArn);
}
else if (isIamRoleArn(principalArn)) {
return getAllPoliciesForRole(collectClient, principalArn);
}
else if (isAssumedRoleArn(principalArn)) {
const roleArn = convertAssumedRoleArnToRoleArn(principalArn);
return getAllPoliciesForRole(collectClient, roleArn);
}
throw new Error(`Unsupported principal type: ${principalArn}`);
}
export function isArnPrincipal(principal) {
return principal.startsWith('arn:');
}
export function isServicePrincipal(principal) {
return !isArnPrincipal(principal) && principal.endsWith('amazonaws.com');
}
export function isServiceLinkedRole(principal) {
const arnParts = splitArnParts(principal);
return isArnPrincipal(principal) && !!arnParts.resourcePath?.startsWith('aws-service-role/');
}
export function isOidcPrincipal(principal) {
if (!isArnPrincipal(principal)) {
return false;
}
const parts = splitArnParts(principal);
return parts.service === 'iam' && parts.resourceType === 'oidc-provider';
}
export function isSamlPrincipal(principal) {
if (!isArnPrincipal(principal)) {
return false;
}
const parts = splitArnParts(principal);
return parts.service === 'iam' && parts.resourceType === 'saml-provider';
}
/**
* Check to see if a principal exists or is an AWS service principal.
*
* @param principal the principal to check
* @param collectClient the IAM collect client to use for checking existence
* @returns true if the principal exists or is a service principal, false otherwise
*/
export async function principalExists(principal, collectClient) {
if (isServicePrincipal(principal)) {
return true;
}
return collectClient.principalExists(principal);
}
//# sourceMappingURL=principals.js.map