slackapi/bolt-js

Using AWS Lambda Handler while retrieving Bot Token and Signing Secret from Vault

Closed this issue · 4 comments

Currently, I'm facing issue using AwsLambdaReceiver.
Specifically, I'm trying to fetch SLACK_BOT_TOKEN and SLACK_SIGNING_SECRET in runtime from vault.
But, it seems your receiver checks existence of those variables before it passes the event to our code.
Is it by design? and if it is, is there any way we can fetch secrets during the runtime?

Reproducible in:

The Slack SDK version

npm ls | grep -o "\S\+@\S\+$" | tr @ ' ' | awk -v q='"' '{print q$1q": "q"^"$2q","}' | grep slack
"slack/bolt": "^3.17.1",

Node.js runtime version

More specifically, trying to run it on public.ecr.aws/lambda/nodejs:18

OS info

  • public.ecr.aws/lambda/nodejs:18
  • x86_64

Steps to reproduce:

(Share the commands to run, source code, and project settings)

  1. First, specify environment variables in Lambda and run, which works.
  2. Next, remove the variables in Lambda and run, which fails with error message slack_bolt_app_initialization_error
  3. Next, specify env variables in Lambda, but the value is dummy. When it runs, the initialization won't fail, but it fails to receive message ( slack_webapi_platform_error)

Expected result:

run successfully

Actual result:

The lambda function is not invoked at all, but instead fails with following message

2024-01-29T13:52:16.335Z	undefined	ERROR	Uncaught Exception 	{
    "errorType": "Error",
    "errorMessage": "Apps used in a single workspace can be initialized with a token. Apps used in many workspaces should be initialized with oauth installer options or authorize. \n\nSince you have not provided a token or authorize, you might be missing one or more required oauth installer options. See https://slack.dev/bolt-js/concepts#authenticating-oauth for these required fields.\n",
    "code": "slack_bolt_app_initialization_error",
    "stack": [
        "Error: Apps used in a single workspace can be initialized with a token. Apps used in many workspaces should be initialized with oauth installer options or authorize. ",
        "",
        "Since you have not provided a token or authorize, you might be missing one or more required oauth installer options. See https://slack.dev/bolt-js/concepts#authenticating-oauth for these required fields.",
        "",
        "    at CW.initAuthorizeIfNoTokenIsGiven (/var/task/app.js:119:35519)",
        "    at CW.initAuthorizeInConstructor (/var/task/app.js:122:247)",
        "    at new CW (/var/task/app.js:119:27094)",
        "    at Object.<anonymous> (/var/task/app.js:231:1895)",
        "    at Module._compile (node:internal/modules/cjs/loader:1356:14)",
        "    at Module._extensions..js (node:internal/modules/cjs/loader:1414:10)",
        "    at Module.load (node:internal/modules/cjs/loader:1197:32)",
        "    at Module._load (node:internal/modules/cjs/loader:1013:12)",
        "    at Module.require (node:internal/modules/cjs/loader:1225:19)",
        "    at require (node:internal/modules/helpers:177:18)"
    ]
}

Requirements

For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. 🙇

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

Is it not possible to retrieve the secrets from your vault before initializing the App and AwsLambdaReceiver?

@filmaj Thaks for your reply!
I actually tried that, but didn't work.
I implemented like following, but lambda function failed with slack_bolt_app_initialization_error and never executed lines in handler.

let sign = process.env.SLACK_SIGNING_SECRET || '';
let token = process.env.SLACK_BOT_TOKEN || '';

async function getSecrets(): Promise {
    const client = new SecretsManagerClient({ region: 'ap-northeast-1' });

    const input = {
        SecretId: 'SecretsName'
    };
    const command = new GetSecretValueCommand(input);    
    try {
        const response = await client.send(command);
        const secret = JSON.parse(response.SecretString || '');
        return secret;
    } catch (error) {
        console.log('fail!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
        console.error('Failed to parse secret string');
        throw error;
    }
}

(async () => {
    await readEnvVariables();
    // rest of your code
    const secrets = await getSecrets();
        sign = secrets.SLACK_SIGNING_SECRET;
        token = secrets.SLACK_BOT_TOKEN;
        process.env.SLACK_BOT_TOKEN = secrets.SLACK_BOT_TOKEN;
        process.env.SLACK_SIGNING_SECRET = secrets.SLACK_SIGNING_SECRET;
})();

const logger = initLogger();

const awsLambdaReceiver = new AwsLambdaReceiver({
      signingSecret: process.env.SLACK_SIGNING_SECRET || '',
    });
const app = new App({
    logger: logger,
    logLevel: logger.getLevel(),
    token: process.env.SLACK_BOT_TOKEN || '',
    receiver: awsLambdaReceiver
});

app.event('app_mention', async ({  event, context, say }) => { // what ever code goes here}

module.exports.handler = async (event: AwsEvent, context: any, callback: AwsCallback) => {
    logger.info('invoked lambda handler')
    logger.debug(`Event: ${JSON.stringify(event, null, 2)}`);
    logger.debug(`Context: ${JSON.stringify(context, null, 2)}`);

      const handler = await awsLambdaReceiver.start()

    return handler(event, context, callback);
};

👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.

As this issue has been inactive for more than one month, we will be closing it. Thank you to all the participants! If you would like to raise a related issue, please create a new issue which includes your specific details and references this issue number.