amazon-web-servicesamazon-cognitoaws-sdkaws-sdk-jsamazon-timestream

AccessDeniedException for the action that is allowed to a role by a policy on AWS timestream


I'm trying to read timestream data from web app for public use. I followed this tutorial from AWS to allow any user to see the data on web browser. After that, I followed this github issue since discovering endpoints was failing.

The problem I'm having now is that it returns these errors now.

POST https://query.timestream.us-west-2.amazonaws.com/ 403 (Forbidden)
Uncaught (in promise) AccessDeniedException: 
User: arn:aws:sts::<number here>:assumed-role/Cognito_izunumaUnauth_Role/CognitoIdentityCredentials 
is not authorized to perform: timestream:DescribeEndpoints because no session policy allows 
the timestream:DescribeEndpoints action

I have already attached a policy to Cognito_izunumaUnauth_Role to allow timestream:DescribeEndpoints and checked that it works on simulator on IAM, so I don't know what to do to resolve this error.

the code looks like this in my react app now.

import * as AWS from "@aws-sdk/client-timestream-query";
import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity";
import {
  fromCognitoIdentityPool,
} from "@aws-sdk/credential-provider-cognito-identity";
import {useEffect} from 'react';

function App() {

  useEffect(()=>{
    (async () => {
      const endpointsQueryClient = new AWS.TimestreamQuery({ 
        region: "us-west-2",
        credentials: fromCognitoIdentityPool({
          client: new CognitoIdentityClient({ region: "us-west-2" }),
          identityPoolId: "<IDENTITY_POOL_ID>",
        })
      });
      const qClientResponse = await endpointsQueryClient.describeEndpoints({});
      console.log(qClientResponse);

      const queryClient = new AWS.TimestreamQuery({
        region: "us-west-2",
        credentials: fromCognitoIdentityPool({
          client: new CognitoIdentityClient({ region: "us-west-2" }),
          identityPoolId: "<IDENTITY_POOL_ID>",
        }),
        endpoint: `https://${qClientResponse.Endpoints[0].Address}`,
      });

      const QueryString = `SELECT * FROM solarpanel_test.solarpanel_test WHERE time between ago(30000m) and now() ORDER BY time DESC LIMIT 200`;
      console.log(await queryClient.query({ QueryString }));

    })()
  },[])

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

I'm new to AWS, so any suggestion would help.


Solution

  • This is the exact issue that I encountered, I thought it is something about authorization, yeah it is quite right but, this error refers to your role, so I use STSClient here,use that role credentials to use the other features of @aws-sdk

    const { STSClient, AssumeRoleCommand } = require("@aws-sdk/client-sts");
    
    const params = {
      RoleArn: "<role>",
      RoleSessionName: "<name>",
    };
    const clientRole = new STSClient({
      region: "us-west-2",
      credentials: aws_creds,
    });
    const roleCommand = new AssumeRoleCommand({
      RoleArn: "<role>",
      RoleSessionName: "<name>",
    })
    const role = await clientRole.send(roleCommand);
    
    const role_creds = {
      accessKeyId: role.Credentials.AccessKeyId,
      secretAccessKey: role.Credentials.SecretAccessKey,
      sessionToken: role.Credentials.SessionToken,
    };
    const query = `SELECT * FROM db.table ORDER BY column DESC LIMIT 5`;
    
    const timestreamQuery = new TimestreamQueryClient({
      region: "us-west-2",
      credentials: role_creds,
    });
    const queryCommand = new QueryCommand({QueryString: query})
    
    // use it like `timestreamQuery.send(queryCommand, (err, data)=> { ... })`