@softchef/cdk-iot-device-management
Version:
IoT device management is composed of things, thing types, thing groups, jobs, files API services. The constructs can be used independently, that are based on full-managed service to create an API Gateway & Lambda function.
89 lines (88 loc) • 4.72 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSsoProfile = exports.validateSsoProfile = exports.fromSSO = exports.EXPIRE_WINDOW_MS = void 0;
const client_sso_1 = require("@aws-sdk/client-sso");
const property_provider_1 = require("@aws-sdk/property-provider");
const shared_ini_file_loader_1 = require("@aws-sdk/shared-ini-file-loader");
const util_credentials_1 = require("@aws-sdk/util-credentials");
const crypto_1 = require("crypto");
const fs_1 = require("fs");
const path_1 = require("path");
exports.EXPIRE_WINDOW_MS = 15 * 60 * 1000;
const SHOULD_FAIL_CREDENTIAL_CHAIN = false;
const fromSSO = (init = {}) => async () => {
const { ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoClient } = init;
if (!ssoStartUrl && !ssoAccountId && !ssoRegion && !ssoRoleName) {
const profiles = await util_credentials_1.parseKnownFiles(init);
const profileName = util_credentials_1.getMasterProfileName(init);
const profile = profiles[profileName];
if (!exports.isSsoProfile(profile)) {
throw new property_provider_1.CredentialsProviderError(`Profile ${profileName} is not configured with SSO credentials.`);
}
const { sso_start_url, sso_account_id, sso_region, sso_role_name } = exports.validateSsoProfile(profile);
return resolveSSOCredentials({
ssoStartUrl: sso_start_url,
ssoAccountId: sso_account_id,
ssoRegion: sso_region,
ssoRoleName: sso_role_name,
ssoClient: ssoClient,
});
}
else if (!ssoStartUrl || !ssoAccountId || !ssoRegion || !ssoRoleName) {
throw new property_provider_1.CredentialsProviderError('Incomplete configuration. The fromSSO() argument hash must include "ssoStartUrl",' +
' "ssoAccountId", "ssoRegion", "ssoRoleName"');
}
else {
return resolveSSOCredentials({ ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoClient });
}
};
exports.fromSSO = fromSSO;
const resolveSSOCredentials = async ({ ssoStartUrl, ssoAccountId, ssoRegion, ssoRoleName, ssoClient, }) => {
const hasher = crypto_1.createHash("sha1");
const cacheName = hasher.update(ssoStartUrl).digest("hex");
const tokenFile = path_1.join(shared_ini_file_loader_1.getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
let token;
try {
token = JSON.parse(fs_1.readFileSync(tokenFile, { encoding: "utf-8" }));
if (new Date(token.expiresAt).getTime() - Date.now() <= exports.EXPIRE_WINDOW_MS) {
throw new Error("SSO token is expired.");
}
}
catch (e) {
throw new property_provider_1.CredentialsProviderError(`The SSO session associated with this profile has expired or is otherwise invalid. To refresh this SSO session ` +
`run aws sso login with the corresponding profile.`, SHOULD_FAIL_CREDENTIAL_CHAIN);
}
const { accessToken } = token;
const sso = ssoClient || new client_sso_1.SSOClient({ region: ssoRegion });
let ssoResp;
try {
ssoResp = await sso.send(new client_sso_1.GetRoleCredentialsCommand({
accountId: ssoAccountId,
roleName: ssoRoleName,
accessToken,
}));
}
catch (e) {
throw property_provider_1.CredentialsProviderError.from(e, SHOULD_FAIL_CREDENTIAL_CHAIN);
}
const { roleCredentials: { accessKeyId, secretAccessKey, sessionToken, expiration } = {} } = ssoResp;
if (!accessKeyId || !secretAccessKey || !sessionToken || !expiration) {
throw new property_provider_1.CredentialsProviderError("SSO returns an invalid temporary credential.", SHOULD_FAIL_CREDENTIAL_CHAIN);
}
return { accessKeyId, secretAccessKey, sessionToken, expiration: new Date(expiration) };
};
const validateSsoProfile = (profile) => {
const { sso_start_url, sso_account_id, sso_region, sso_role_name } = profile;
if (!sso_start_url || !sso_account_id || !sso_region || !sso_role_name) {
throw new property_provider_1.CredentialsProviderError(`Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", "sso_region", ` +
`"sso_role_name", "sso_start_url". Got ${Object.keys(profile).join(", ")}\nReference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html`, SHOULD_FAIL_CREDENTIAL_CHAIN);
}
return profile;
};
exports.validateSsoProfile = validateSsoProfile;
const isSsoProfile = (arg) => arg &&
(typeof arg.sso_start_url === "string" ||
typeof arg.sso_account_id === "string" ||
typeof arg.sso_region === "string" ||
typeof arg.sso_role_name === "string");
exports.isSsoProfile = isSsoProfile;