190 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
var getHomeDir = require('./getHomeDir');
 | 
						|
var getSSOTokenFilepath = require('./getSSOTokenFilepath');
 | 
						|
var getSSOTokenFromFile = require('./getSSOTokenFromFile');
 | 
						|
var path = require('path');
 | 
						|
var types = require('@smithy/types');
 | 
						|
var slurpFile = require('./slurpFile');
 | 
						|
 | 
						|
const ENV_PROFILE = "AWS_PROFILE";
 | 
						|
const DEFAULT_PROFILE = "default";
 | 
						|
const getProfileName = (init) => init.profile || process.env[ENV_PROFILE] || DEFAULT_PROFILE;
 | 
						|
 | 
						|
const getConfigData = (data) => Object.entries(data)
 | 
						|
    .filter(([key]) => {
 | 
						|
    const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
 | 
						|
    if (indexOfSeparator === -1) {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    return Object.values(types.IniSectionType).includes(key.substring(0, indexOfSeparator));
 | 
						|
})
 | 
						|
    .reduce((acc, [key, value]) => {
 | 
						|
    const indexOfSeparator = key.indexOf(CONFIG_PREFIX_SEPARATOR);
 | 
						|
    const updatedKey = key.substring(0, indexOfSeparator) === types.IniSectionType.PROFILE ? key.substring(indexOfSeparator + 1) : key;
 | 
						|
    acc[updatedKey] = value;
 | 
						|
    return acc;
 | 
						|
}, {
 | 
						|
    ...(data.default && { default: data.default }),
 | 
						|
});
 | 
						|
 | 
						|
const ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
 | 
						|
const getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || path.join(getHomeDir.getHomeDir(), ".aws", "config");
 | 
						|
 | 
						|
const ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
 | 
						|
const getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || path.join(getHomeDir.getHomeDir(), ".aws", "credentials");
 | 
						|
 | 
						|
const prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@\+\.%:/]+)\2$/;
 | 
						|
const profileNameBlockList = ["__proto__", "profile __proto__"];
 | 
						|
const parseIni = (iniData) => {
 | 
						|
    const map = {};
 | 
						|
    let currentSection;
 | 
						|
    let currentSubSection;
 | 
						|
    for (const iniLine of iniData.split(/\r?\n/)) {
 | 
						|
        const trimmedLine = iniLine.split(/(^|\s)[;#]/)[0].trim();
 | 
						|
        const isSection = trimmedLine[0] === "[" && trimmedLine[trimmedLine.length - 1] === "]";
 | 
						|
        if (isSection) {
 | 
						|
            currentSection = undefined;
 | 
						|
            currentSubSection = undefined;
 | 
						|
            const sectionName = trimmedLine.substring(1, trimmedLine.length - 1);
 | 
						|
            const matches = prefixKeyRegex.exec(sectionName);
 | 
						|
            if (matches) {
 | 
						|
                const [, prefix, , name] = matches;
 | 
						|
                if (Object.values(types.IniSectionType).includes(prefix)) {
 | 
						|
                    currentSection = [prefix, name].join(CONFIG_PREFIX_SEPARATOR);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                currentSection = sectionName;
 | 
						|
            }
 | 
						|
            if (profileNameBlockList.includes(sectionName)) {
 | 
						|
                throw new Error(`Found invalid profile name "${sectionName}"`);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else if (currentSection) {
 | 
						|
            const indexOfEqualsSign = trimmedLine.indexOf("=");
 | 
						|
            if (![0, -1].includes(indexOfEqualsSign)) {
 | 
						|
                const [name, value] = [
 | 
						|
                    trimmedLine.substring(0, indexOfEqualsSign).trim(),
 | 
						|
                    trimmedLine.substring(indexOfEqualsSign + 1).trim(),
 | 
						|
                ];
 | 
						|
                if (value === "") {
 | 
						|
                    currentSubSection = name;
 | 
						|
                }
 | 
						|
                else {
 | 
						|
                    if (currentSubSection && iniLine.trimStart() === iniLine) {
 | 
						|
                        currentSubSection = undefined;
 | 
						|
                    }
 | 
						|
                    map[currentSection] = map[currentSection] || {};
 | 
						|
                    const key = currentSubSection ? [currentSubSection, name].join(CONFIG_PREFIX_SEPARATOR) : name;
 | 
						|
                    map[currentSection][key] = value;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return map;
 | 
						|
};
 | 
						|
 | 
						|
const swallowError$1 = () => ({});
 | 
						|
const CONFIG_PREFIX_SEPARATOR = ".";
 | 
						|
const loadSharedConfigFiles = async (init = {}) => {
 | 
						|
    const { filepath = getCredentialsFilepath(), configFilepath = getConfigFilepath() } = init;
 | 
						|
    const homeDir = getHomeDir.getHomeDir();
 | 
						|
    const relativeHomeDirPrefix = "~/";
 | 
						|
    let resolvedFilepath = filepath;
 | 
						|
    if (filepath.startsWith(relativeHomeDirPrefix)) {
 | 
						|
        resolvedFilepath = path.join(homeDir, filepath.slice(2));
 | 
						|
    }
 | 
						|
    let resolvedConfigFilepath = configFilepath;
 | 
						|
    if (configFilepath.startsWith(relativeHomeDirPrefix)) {
 | 
						|
        resolvedConfigFilepath = path.join(homeDir, configFilepath.slice(2));
 | 
						|
    }
 | 
						|
    const parsedFiles = await Promise.all([
 | 
						|
        slurpFile.slurpFile(resolvedConfigFilepath, {
 | 
						|
            ignoreCache: init.ignoreCache,
 | 
						|
        })
 | 
						|
            .then(parseIni)
 | 
						|
            .then(getConfigData)
 | 
						|
            .catch(swallowError$1),
 | 
						|
        slurpFile.slurpFile(resolvedFilepath, {
 | 
						|
            ignoreCache: init.ignoreCache,
 | 
						|
        })
 | 
						|
            .then(parseIni)
 | 
						|
            .catch(swallowError$1),
 | 
						|
    ]);
 | 
						|
    return {
 | 
						|
        configFile: parsedFiles[0],
 | 
						|
        credentialsFile: parsedFiles[1],
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
const getSsoSessionData = (data) => Object.entries(data)
 | 
						|
    .filter(([key]) => key.startsWith(types.IniSectionType.SSO_SESSION + CONFIG_PREFIX_SEPARATOR))
 | 
						|
    .reduce((acc, [key, value]) => ({ ...acc, [key.substring(key.indexOf(CONFIG_PREFIX_SEPARATOR) + 1)]: value }), {});
 | 
						|
 | 
						|
const swallowError = () => ({});
 | 
						|
const loadSsoSessionData = async (init = {}) => slurpFile.slurpFile(init.configFilepath ?? getConfigFilepath())
 | 
						|
    .then(parseIni)
 | 
						|
    .then(getSsoSessionData)
 | 
						|
    .catch(swallowError);
 | 
						|
 | 
						|
const mergeConfigFiles = (...files) => {
 | 
						|
    const merged = {};
 | 
						|
    for (const file of files) {
 | 
						|
        for (const [key, values] of Object.entries(file)) {
 | 
						|
            if (merged[key] !== undefined) {
 | 
						|
                Object.assign(merged[key], values);
 | 
						|
            }
 | 
						|
            else {
 | 
						|
                merged[key] = values;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return merged;
 | 
						|
};
 | 
						|
 | 
						|
const parseKnownFiles = async (init) => {
 | 
						|
    const parsedFiles = await loadSharedConfigFiles(init);
 | 
						|
    return mergeConfigFiles(parsedFiles.configFile, parsedFiles.credentialsFile);
 | 
						|
};
 | 
						|
 | 
						|
const externalDataInterceptor = {
 | 
						|
    getFileRecord() {
 | 
						|
        return slurpFile.fileIntercept;
 | 
						|
    },
 | 
						|
    interceptFile(path, contents) {
 | 
						|
        slurpFile.fileIntercept[path] = Promise.resolve(contents);
 | 
						|
    },
 | 
						|
    getTokenRecord() {
 | 
						|
        return getSSOTokenFromFile.tokenIntercept;
 | 
						|
    },
 | 
						|
    interceptToken(id, contents) {
 | 
						|
        getSSOTokenFromFile.tokenIntercept[id] = contents;
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
Object.defineProperty(exports, "getSSOTokenFromFile", {
 | 
						|
    enumerable: true,
 | 
						|
    get: function () { return getSSOTokenFromFile.getSSOTokenFromFile; }
 | 
						|
});
 | 
						|
exports.CONFIG_PREFIX_SEPARATOR = CONFIG_PREFIX_SEPARATOR;
 | 
						|
exports.DEFAULT_PROFILE = DEFAULT_PROFILE;
 | 
						|
exports.ENV_PROFILE = ENV_PROFILE;
 | 
						|
exports.externalDataInterceptor = externalDataInterceptor;
 | 
						|
exports.getProfileName = getProfileName;
 | 
						|
exports.loadSharedConfigFiles = loadSharedConfigFiles;
 | 
						|
exports.loadSsoSessionData = loadSsoSessionData;
 | 
						|
exports.parseKnownFiles = parseKnownFiles;
 | 
						|
Object.keys(getHomeDir).forEach(function (k) {
 | 
						|
    if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
 | 
						|
        enumerable: true,
 | 
						|
        get: function () { return getHomeDir[k]; }
 | 
						|
    });
 | 
						|
});
 | 
						|
Object.keys(getSSOTokenFilepath).forEach(function (k) {
 | 
						|
    if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
 | 
						|
        enumerable: true,
 | 
						|
        get: function () { return getSSOTokenFilepath[k]; }
 | 
						|
    });
 | 
						|
});
 |