@cloud-copilot/iam-collect
Version:
Collect IAM information from AWS Accounts
346 lines • 13.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultAuthConfig = getDefaultAuthConfig;
exports.servicesForAccount = servicesForAccount;
exports.customConfigForSync = customConfigForSync;
exports.configuredRegionListForAccount = configuredRegionListForAccount;
exports.regionsForService = regionsForService;
exports.accountServiceRegionConfig = accountServiceRegionConfig;
exports.getAccountAuthConfig = getAccountAuthConfig;
exports.getStorageConfig = getStorageConfig;
exports.syncEnabledForRegion = syncEnabledForRegion;
exports.getConfiguredAccounts = getConfiguredAccounts;
exports.getConfiguredDataSource = getConfiguredDataSource;
/**
* Get the default auth config from the provided configs.
*
* @param configs the configs to search for the default auth config
* @returns the default auth config, or an empty object if none found
*/
function getDefaultAuthConfig(configs) {
// Return the last config with an auth config, or an empty object if none found
for (let i = configs.length - 1; i >= 0; i--) {
const configAuth = configs[i].auth;
if (configAuth) {
return configAuth;
}
}
return {};
}
function servicesForAccount(account, configs, allServices) {
let services = allServices;
for (const config of configs) {
if (config.services?.included) {
services = intersection(allServices, config.services.included);
}
if (config.services?.excluded) {
services = difference(services, config.services.excluded);
}
const accountServices = config.accountConfigs?.[account]?.services;
if (accountServices) {
if (accountServices.included) {
for (const service of accountServices.included) {
if (!services.includes(service) && allServices.includes(service)) {
services.push(service);
}
}
}
if (accountServices.excluded) {
services = difference(services, accountServices.excluded);
}
}
}
return services;
}
/**
* Look up the custom config for a specific sync for a service in an account and region.
*
* @param service the service to look up the sync for
* @param syncName the name of the sync to look up
* @param account the account to look up the sync for
* @param region the region to look up the sync for
* @param configs the configs to search
* @returns the custom config for the sync, or undefined if not found
*/
function customConfigForSync(service, syncName, account, region, configs) {
// Look up the custom config for the specified service and sync name
for (const config of [...configs].reverse()) {
const accountServiceConfig = config.accountConfigs?.[account]?.serviceConfigs?.[service];
const accountServiceRegionConfig = accountServiceConfig?.regionConfigs?.[region]?.syncConfigs?.[syncName];
if (accountServiceRegionConfig?.custom) {
return accountServiceRegionConfig.custom;
}
if (accountServiceConfig?.syncConfigs?.[syncName]?.custom) {
return accountServiceConfig.syncConfigs[syncName].custom;
}
const serviceRegionConfig = config.serviceConfigs?.[service]?.regionConfigs?.[region];
if (serviceRegionConfig?.syncConfigs?.[syncName]?.custom) {
return serviceRegionConfig.syncConfigs[syncName].custom;
}
const serviceConfig = config.serviceConfigs?.[service];
if (serviceConfig?.syncConfigs?.[syncName]?.custom) {
return serviceConfig.syncConfigs[syncName].custom;
}
}
return undefined;
}
/**
* Look up the region list from the provided configs, if any.
*
* @param configs the configs to search
* @param accountId the account id to look up the region list for
* @returns the configured region list for the account, or undefined if none found
*/
function configuredRegionListForAccount(configs, accountId) {
let accountRegionList = undefined;
let masterRegionList = undefined;
for (const config of configs) {
if (config.accountConfigs?.[accountId]?.regions?.included) {
accountRegionList = config.accountConfigs[accountId].regions.included;
}
if (config.regions?.included) {
masterRegionList = config.regions.included;
}
}
return accountRegionList || masterRegionList;
}
/**
* Get the regions for a specific service and account.
*
* @param service the service to get the regions for
* @param account the account to get the regions for
* @param configs the configs to search
* @param allRegions the list of all regions to filter from
* @returns the regions for the service and account
*/
function regionsForService(service, account, configs, allRegions) {
let regions = allRegions;
for (const config of configs) {
if (config.regions?.included) {
regions = intersection(allRegions, config.regions.included);
}
if (config.regions?.excluded) {
regions = difference(regions, config.regions.excluded);
}
const serviceConfig = config.serviceConfigs?.[service];
if (serviceConfig) {
if (serviceConfig.regions?.included) {
regions = intersection(allRegions, serviceConfig.regions.included);
}
if (serviceConfig.regions?.excluded) {
regions = difference(regions, serviceConfig.regions.excluded);
}
}
const accountConfig = config.accountConfigs?.[account];
if (accountConfig) {
if (accountConfig.regions?.included) {
regions = intersection(allRegions, accountConfig.regions.included);
}
if (accountConfig.regions?.excluded) {
regions = difference(regions, accountConfig.regions.excluded);
}
const accountServices = accountConfig.serviceConfigs?.[service];
if (accountServices) {
if (accountServices.regions?.included) {
regions = intersection(allRegions, accountServices.regions.included);
}
if (accountServices.regions?.excluded) {
regions = difference(regions, accountServices.regions.excluded);
}
}
}
}
return regions;
}
function accountServiceRegionConfig(service, accountId, region, configs) {
let result = {
accountId: accountId,
service,
region
};
for (const config of configs) {
if (config.auth) {
result.auth = config.auth;
}
const serviceConfig = config.serviceConfigs?.[service];
if (serviceConfig) {
if (serviceConfig.auth) {
result.auth = mergeAuthConfigs(result.auth, serviceConfig.auth);
}
if (serviceConfig.endpoint) {
result.endpoint = serviceConfig.endpoint;
}
const regionConfig = serviceConfig.regionConfigs?.[region];
if (regionConfig) {
if (regionConfig.auth) {
result.auth = mergeAuthConfigs(result.auth, regionConfig.auth);
}
if (regionConfig.endpoint) {
result.endpoint = regionConfig.endpoint;
}
}
}
const accountConfig = config.accountConfigs?.[accountId];
if (accountConfig) {
if (accountConfig.auth) {
result.auth = mergeAuthConfigs(result.auth, accountConfig.auth);
}
const accountServiceConfig = accountConfig.serviceConfigs?.[service];
if (accountServiceConfig) {
if (accountServiceConfig.auth) {
result.auth = mergeAuthConfigs(result.auth, accountServiceConfig.auth);
}
if (accountServiceConfig.endpoint) {
result.endpoint = accountServiceConfig.endpoint;
}
const accountRegionConfig = accountServiceConfig.regionConfigs?.[region];
if (accountRegionConfig) {
if (accountRegionConfig.auth) {
result.auth = mergeAuthConfigs(result.auth, accountRegionConfig.auth);
}
if (accountRegionConfig.endpoint) {
result.endpoint = accountRegionConfig.endpoint;
}
}
}
}
}
return result;
}
/**
* Get the auth config for a specific account
*
* @param accountId the account id to get the auth config for
* @param configs the configs to search
* @returns the auth config for the account, or undefined if not found
*/
function getAccountAuthConfig(accountId, configs) {
let result = undefined;
for (const config of configs) {
if (config.auth) {
result = config.auth;
}
const accountConfig = config.accountConfigs?.[accountId];
if (accountConfig?.auth) {
result = mergeAuthConfigs(result, accountConfig.auth);
}
}
return result;
}
function getStorageConfig(configs) {
const reverseConfigs = [...configs].reverse();
// Iterate through the configs to find the first storage config
for (const config of reverseConfigs) {
if (config.storage) {
return config.storage;
}
}
// Return undefined if no storage config is found
return undefined;
}
/**
* Check if a specific sync is enabled for given region. This checks the specific sync config within the service.
*
* This should only be used after the sync has been validated to be enabled for the account and service.
*
* @param accountId the account id to check
* @param service the service to check
* @param syncName the specific name of the sync to check
* @param configs the configs to check
* @param region the region being tested
* @returns true if the sync is enabled for the region, false otherwise
*/
function syncEnabledForRegion(accountId, service, syncName, configs, region) {
// go through the configs in reverse order,
// If any have the sync enabled return true,
// If any have the sync disabled return false
// If none are found, return true
for (const config of [...configs].reverse()) {
const accountServiceConfig = config.accountConfigs?.[accountId]?.serviceConfigs?.[service]?.syncConfigs?.[syncName];
if (accountServiceConfig) {
if (accountServiceConfig.regions?.excluded?.includes(region)) {
return false;
}
if (accountServiceConfig.regions?.included) {
return accountServiceConfig.regions.included.includes(region);
}
}
const serviceConfig = config.serviceConfigs?.[service]?.syncConfigs?.[syncName];
if (serviceConfig) {
if (serviceConfig.regions?.excluded?.includes(region)) {
return false;
}
if (serviceConfig.regions?.included) {
return serviceConfig.regions.included.includes(region);
}
}
}
return true;
}
/**
* Get the default accounts from the provided configs.
*
* @param configs the configs to search for the default accounts
* @returns the default accounts, or an empty array if none found
*/
function getConfiguredAccounts(configs) {
const reverseConfigs = [...configs].reverse();
for (const config of reverseConfigs) {
if (config.accounts?.included) {
return config.accounts.included;
}
}
return [];
}
/**
* Get the data source configuration from the provided configs.
*
* @param configs the configs to search for the data source configuration
* @returns the data source configuration, or undefined if none found
*/
function getConfiguredDataSource(configs) {
const reverseConfigs = [...configs].reverse();
for (const config of reverseConfigs) {
if (config.dataSource) {
return config.dataSource;
}
}
return undefined;
}
function mergeAuthConfigs(initialConfig, newConfig) {
if (!initialConfig) {
initialConfig = {};
}
if (!newConfig) {
return initialConfig;
}
initialConfig = structuredClone(initialConfig);
if ('profile' in newConfig) {
initialConfig.profile = newConfig.profile;
}
if ('initialRole' in newConfig) {
if (newConfig.initialRole === null) {
delete initialConfig.initialRole;
}
else {
initialConfig.initialRole = {
...(initialConfig.initialRole || {}),
...newConfig.initialRole
};
}
}
if ('role' in newConfig) {
initialConfig.role = {
...(initialConfig.role || {}),
...newConfig.role
};
}
return initialConfig;
}
function intersection(a, b) {
return a.filter((value) => b.includes(value));
}
function difference(a, b) {
return a.filter((value) => !b.includes(value));
}
//# sourceMappingURL=config.js.map