"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
var http = _interopRequireWildcard(require("http"), true);
var https = _interopRequireWildcard(require("https"), true);
var _url = require("url");
var _CredentialProvider = require("./CredentialProvider.js");
var _Credentials = require("./Credentials.js");
var _helper = require("./internal/helper.js");
var _request = require("./internal/request.js");
var _response = require("./internal/response.js");
var _signing = require("./signing.js");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
/**
 * @see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
 */

const defaultExpirySeconds = 900;
class AssumeRoleProvider extends _CredentialProvider.CredentialProvider {
  accessExpiresAt = '';
  constructor({
    stsEndpoint,
    accessKey,
    secretKey,
    durationSeconds = defaultExpirySeconds,
    sessionToken,
    policy,
    region = '',
    roleArn,
    roleSessionName,
    externalId,
    token,
    webIdentityToken,
    action = 'AssumeRole',
    transportAgent = undefined
  }) {
    super({
      accessKey,
      secretKey,
      sessionToken
    });
    this.stsEndpoint = new _url.URL(stsEndpoint);
    this.accessKey = accessKey;
    this.secretKey = secretKey;
    this.policy = policy;
    this.region = region;
    this.roleArn = roleArn;
    this.roleSessionName = roleSessionName;
    this.externalId = externalId;
    this.token = token;
    this.webIdentityToken = webIdentityToken;
    this.action = action;
    this.durationSeconds = parseInt(durationSeconds);
    let expirySeconds = this.durationSeconds;
    if (this.durationSeconds < defaultExpirySeconds) {
      expirySeconds = defaultExpirySeconds;
    }
    this.expirySeconds = expirySeconds; // for calculating refresh of credentials.

    // By default, nodejs uses a global agent if the 'agent' property
    // is set to undefined. Otherwise, it's okay to assume the users
    // know what they're doing if they specify a custom transport agent.
    this.transportAgent = transportAgent;
    const isHttp = this.stsEndpoint.protocol === 'http:';
    this.transport = isHttp ? http : https;

    /**
     * Internal Tracking variables
     */
    this._credentials = null;
  }
  getRequestConfig() {
    const hostValue = this.stsEndpoint.hostname;
    const portValue = this.stsEndpoint.port;
    const qryParams = new _url.URLSearchParams({
      Action: this.action,
      Version: '2011-06-15'
    });
    qryParams.set('DurationSeconds', this.expirySeconds.toString());
    if (this.policy) {
      qryParams.set('Policy', this.policy);
    }
    if (this.roleArn) {
      qryParams.set('RoleArn', this.roleArn);
    }
    if (this.roleSessionName != null) {
      qryParams.set('RoleSessionName', this.roleSessionName);
    }
    if (this.token != null) {
      qryParams.set('Token', this.token);
    }
    if (this.webIdentityToken) {
      qryParams.set('WebIdentityToken', this.webIdentityToken);
    }
    if (this.externalId) {
      qryParams.set('ExternalId', this.externalId);
    }
    const urlParams = qryParams.toString();
    const contentSha256 = (0, _helper.toSha256)(urlParams);
    const date = new Date();
    const requestOptions = {
      hostname: hostValue,
      port: portValue,
      path: '/',
      protocol: this.stsEndpoint.protocol,
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'content-length': urlParams.length.toString(),
        host: hostValue,
        'x-amz-date': (0, _helper.makeDateLong)(date),
        'x-amz-content-sha256': contentSha256
      },
      agent: this.transportAgent
    };
    requestOptions.headers.authorization = (0, _signing.signV4ByServiceName)(requestOptions, this.accessKey, this.secretKey, this.region, date, contentSha256, 'sts');
    return {
      requestOptions,
      requestData: urlParams
    };
  }
  async performRequest() {
    const {
      requestOptions,
      requestData
    } = this.getRequestConfig();
    const res = await (0, _request.request)(this.transport, requestOptions, requestData);
    const body = await (0, _response.readAsString)(res);
    return (0, _helper.parseXml)(body);
  }
  parseCredentials(respObj) {
    if (respObj.ErrorResponse) {
      var _respObj$ErrorRespons, _respObj$ErrorRespons2, _respObj$ErrorRespons3, _respObj$ErrorRespons4;
      throw new Error(`Unable to obtain credentials: ${(_respObj$ErrorRespons = respObj.ErrorResponse) === null || _respObj$ErrorRespons === void 0 ? void 0 : (_respObj$ErrorRespons2 = _respObj$ErrorRespons.Error) === null || _respObj$ErrorRespons2 === void 0 ? void 0 : _respObj$ErrorRespons2.Code} ${(_respObj$ErrorRespons3 = respObj.ErrorResponse) === null || _respObj$ErrorRespons3 === void 0 ? void 0 : (_respObj$ErrorRespons4 = _respObj$ErrorRespons3.Error) === null || _respObj$ErrorRespons4 === void 0 ? void 0 : _respObj$ErrorRespons4.Message}`, {
        cause: respObj
      });
    }
    const {
      AssumeRoleResponse: {
        AssumeRoleResult: {
          Credentials: {
            AccessKeyId: accessKey,
            SecretAccessKey: secretKey,
            SessionToken: sessionToken,
            Expiration: expiresAt
          }
        }
      }
    } = respObj;
    this.accessExpiresAt = expiresAt;
    return new _Credentials.Credentials({
      accessKey,
      secretKey,
      sessionToken
    });
  }
  async refreshCredentials() {
    try {
      const assumeRoleCredentials = await this.performRequest();
      this._credentials = this.parseCredentials(assumeRoleCredentials);
    } catch (err) {
      throw new Error(`Failed to get Credentials: ${err}`, {
        cause: err
      });
    }
    return this._credentials;
  }
  async getCredentials() {
    if (this._credentials && !this.isAboutToExpire()) {
      return this._credentials;
    }
    this._credentials = await this.refreshCredentials();
    return this._credentials;
  }
  isAboutToExpire() {
    const expiresAt = new Date(this.accessExpiresAt);
    const provisionalExpiry = new Date(Date.now() + 1000 * 10); // check before 10 seconds.
    return provisionalExpiry > expiresAt;
  }
}

// deprecated default export, please use named exports.
// keep for backward compatibility.
// eslint-disable-next-line import/no-default-export
exports.AssumeRoleProvider = AssumeRoleProvider;
var _default = AssumeRoleProvider;
exports.default = _default;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,[encoded data, 19932 characters]