getSigninToken through aws lambda function failed - nodejs

0

This is a very weird problem, I am trying to assme a role and then get signinToken by nodejs through lambda function.

If I use a IAM user's ak/sk to assume the role (arn:aws:iam::432127183xxx:role/ssm-test) to get Credentials, and then use this Credentials to get signinToken, it works fine. But is I use lambda role to assume role (arn:aws:iam::432127183xxx:role/ssm-test) to get Credentials, and then use this Credentials to get signinToken, it works failed. Got below error response from "https://ap-southeast-1.signin.aws.amazon.com/federation" get request: "code":"ERR_BAD_REQUEST","status":400

Below is code Successful code:

const axios = require('axios').default;
var AWS = require('aws-sdk');

exports.handler = async (event) => {

    const { accessKeyId, secretAccessKey, sessionToken } = await getCredentialsForRole();
    
    await generateSigninSSMConsoleLink(accessKeyId, secretAccessKey, sessionToken);
};

async function getCredentialsForRole() {  
  const stsEndpoint = 'https://sts.ap-southeast-1.amazonaws.com';

  AWS.config.update(
    { 
      stsRegionalEndpoints: 'regional',
      region: 'ap-southeast-1', 
      maxRetries: 6, 
      retryDelayOptions: { base: 1000 },
      accessKeyId: 'xxx',      //accessKeyId and secretAccessKey is my IAM user AK/SK
      secretAccessKey: 'xxx',      
    });

  const sts = new AWS.STS({ apiVersion: '2011-06-15', endpoint: stsEndpoint });

  const params = {
      RoleArn: 'arn:aws:iam::432127183xxx:role/ssm-test',
      RoleSessionName: 'test',
    };    

  const { Credentials: creds } = await sts.assumeRole(params).promise();
  const { AccessKeyId: accessKeyId, SecretAccessKey: secretAccessKey, SessionToken: sessionToken } = creds;

  return { accessKeyId, secretAccessKey, sessionToken };
}

async function generateSigninSSMConsoleLink(accessKeyId, secretAccessKey, sessionToken) {
  const session = {'sessionId': accessKeyId,
  'sessionKey': secretAccessKey,
  'sessionToken': sessionToken}

  const params={'Action': 'getSigninToken',
    'SessionDuration': 43200,
    'Session': session};

  const getSigninTokenURL = `https://signin.aws.amazon.com/federation`;

  const response = await axios.get(getSigninTokenURL, {params}); 

  const signinToken = response.data.SigninToken;

  return signinToken
} 

Below is code failed code:

const axios = require('axios').default;
var AWS = require('aws-sdk');

exports.handler = async (event) => {

    const { accessKeyId, secretAccessKey, sessionToken } = await getCredentialsForRole();
    
    await generateSigninSSMConsoleLink(accessKeyId, secretAccessKey, sessionToken);
};

async function getCredentialsForRole() {  
  const stsEndpoint = 'https://sts.ap-southeast-1.amazonaws.com';

  AWS.config.update(
    { 
      stsRegionalEndpoints: 'regional',
      region: 'ap-southeast-1', 
      maxRetries: 6, 
      retryDelayOptions: { base: 1000 },     
    });

  const sts = new AWS.STS({ apiVersion: '2011-06-15', endpoint: stsEndpoint });

  const params = {
      RoleArn: 'arn:aws:iam::432127183xxx:role/ssm-test',
      RoleSessionName: 'test',
    };    

  const { Credentials: creds } = await sts.assumeRole(params).promise();
  const { AccessKeyId: accessKeyId, SecretAccessKey: secretAccessKey, SessionToken: sessionToken } = creds;

  return { accessKeyId, secretAccessKey, sessionToken };
}

async function generateSigninSSMConsoleLink(accessKeyId, secretAccessKey, sessionToken) {
  const session = {'sessionId': accessKeyId,
  'sessionKey': secretAccessKey,
  'sessionToken': sessionToken}

  const params={'Action': 'getSigninToken',
    'SessionDuration': 43200,
    'Session': session};

  const getSigninTokenURL = `https://signin.aws.amazon.com/federation`;

  const response = await axios.get(getSigninTokenURL, {params}); 

  const signinToken = response.data.SigninToken;

  return signinToken
} 

only difference between successful code and failed code is:

      accessKeyId: 'xxx',      //accessKeyId and secretAccessKey is my IAM user AK/SK
      secretAccessKey: 'xxx', 

As I mentioned before, if I user a IAM user to assume role, then can get signintoken if I use lambda role to assume role, then cannot get signinToken.

Who can tell what's wrong?

1 Answer
1

The issue is likely with setting 'SessionDuration': 43200 - there is generally a session duration limit of 1 hour when role chaining [1]. It appears that this limit likely also applies to the getSigninToken action. To make it work with role chaining, try changing the SessionDuration parameter to a value between 900 and 3600 seconds [2].

[1] https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html
[2] https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html

Ed
answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions