CredentialsError: Could not load credentials from ChainableTemporaryCredentials in AWS-SDK v2 for Javascript - aws-sdk

I am trying to set up temporary credentials in the AWS-SDK v2 for Javascript:
const aws = require('aws-sdk')
aws.config = new aws.Config({
credentials: new aws.ChainableTemporaryCredentials({
params: {
RoleArn: roleArn, // Defined earlier
RoleSessionName: sessionName, // Defined earlier
DurationSeconds: 15 * 60
},
masterCredentials: new aws.Credentials({
accessKeyId: accessKeyId, // Defined earlier
secretAccessKey: awsSecretAccessKey // Defined earlier
})
}),
region: 'us-east-1',
signatureVersion: 'v4'
})
aws.config.getCredentials(function (err) {
if (err) console.log(err.stack)
else console.log('Access key:', aws.config.credentials.accessKeyId)
})
However, I'm keep getting the following error, which occurs when calling getCredentials:
CredentialsError: Could not load credentials from ChainableTemporaryCredentials
Note that it works fine if I set the credentials parameter to the master credentials instead of the temporary credentials, as shown below:
aws.config = new aws.Config({
credentials: new aws.Credentials({
accessKeyId: accessKeyId, // Defined earlier
secretAccessKey: awsSecretAccessKey // Defined earlier
}),
region: 'us-east-1',
signatureVersion: 'v4'
})
Does anyone know what's causing this issue? Here's the documentation I was referencing:
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Credentials.html
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ChainableTemporaryCredentials.html

I was finally able to figure out the cause of this error.
What led me to figure out the cause of the error was when I printed out the full error instead of just the most recent error. One of the properties of the error was:
originalError: {
message: 'The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.',
code: 'SignatureDoesNotMatch',
time: 2021-12-11T19:49:52.395Z,
requestId: '402e4c32-7989-4287-a6a9-628bfc93f60f',
statusCode: 403,
retryable: false,
retryDelay: 39.60145242362791
}
So I realized the problem was that my masters credentials I provided were not correct!
I have actually always known that these credentials weren't correct, but for unit-testing purposes it seemed to work fine with these incorrect credentials as long as I didn't also supply the temporary credentials. But now I understand that the getCredentials function verifies the credentials with AWS if you're using temporary credentials, but doesn't verify with AWS when using just master credentials. That explains that strange behavior I was seeing.

Related

Github Actions: Build Failing for NEXT JS PWA App

I have set up Unit tests to be run before pushing to the main branch via GitHub-actions. All the Unit tests are running successfully but for some reason during the build:
Ran all test suites.
info - Checking validity of types...
info - Creating an optimized production build...
warn - using beta Middleware (not covered by semver)
After this step, it fails with the error:
> Build error occurred
Error: Service account object must contain a string "project_id" property.
This error comes from the Firebase Admin SDK Configuration file as shown below:
import admin from 'firebase-admin';
const keyString = process.env.FB_ADMIN_PRIVATE_KEY ?? '{"privateKey": ""}';
const { privateKey } = JSON.parse(keyString);
if (privateKey === '') {
console.log('FIREBASE_PRIVATE_KEY is not set');
if (process.env.NODE_ENV === 'development')
throw new Error('FIREBASE_PRIVATE_KEY is not set');
else console.log('Firebase Private Key Error');
}
if (admin.apps.length === 0)
admin.initializeApp({
credential: admin.credential.cert({
clientEmail: process.env.FB_ADMIN_CLIENT_EMAIL,
privateKey: privateKey,
projectId: process.env.NEXT_PUBLIC_FB_CLIENT_PROJECT_ID,
}),
databaseURL: process.env.FB_ADMIN_RTDB_URL,
});
const db = admin.firestore();
const auth = admin.auth();
const storage = admin.storage();
const rdb = admin.database();
const Server = { auth, db, storage, rdb };
export default Server;
However, I am not sure why is this method even called? Since I have my .env secrets stored in the local, the build seems to succeed there and fail in Github actions. What should I do to resolve this error?
Since NEXT JS Generates static pages and so I was using Admin SDK to fetch some metadata at the server-side and that's why the function was triggered causing it to fail in Github Actions, seems like the only way out here will be to somehow mock the data in order for the actions to run smoothly.

blockchain tutorial Error: The send transactions "from" field must be defined

I am following a blockchain tutorial from dappuniversity.
When I create the task in the line
await App.todoList.createTask(content)
from line
https://github.com/dappuniversity/eth-todo-list/blob/e3ed9a2cefb581c09730250c56c9d30a19cc63c8/src/app.js#L115
I get the following error :
Uncaught (in promise) Error: The send transactions "from" field must be defined!
at Method.inputTransactionFormatter (truffle-contract.js:50747)
at truffle-contract.js:51228
at Array.map (<anonymous>)
at Method.formatInput (truffle-contract.js:51226)
at Method.toPayload (truffle-contract.js:51261)
at Eth.send [as sendTransaction] (truffle-contract.js:51551)
Do I need to define a 'from' field somewhere?
With the latest dependencies, none of the above answers were working for me.
I had to edit the loadAccount method:
loadAccount: async () => {
// Set the current blockchain account
const accounts = await web3.eth.getAccounts();
App.account = accounts[0];
},
then pass the App's account to the createTask method: await App.todoList.createTask(content, { from: App.account })
I was running into issues with the above answer which appears due to recent Metamask updates and that moving from web3.currentProvider to window.ethereum
I was able to make this work using
await App.todoList.createTask(content, {from: App.account})
I am using the latest truffle/contract. I needed to specify the from account in my createTask method like the following:
await App.todoList.createTask(content, { from: web3.eth.defaultAccount})
This worked.
Same happened to me on Remix while interacting with the contract deployed on Rinkeby. I chose injected web3 for the environment, But account field was empty.
It happended because I rejected the connection to metamask first and then did not get any other request to connect with metamask. So I refreshed remix, locked and unlocked metamask. It sent request to connect to metamask

Node Lambda: MySQL query never runs

Testing with Postman, I'll try to make this as clear as possible, please advise if this is not making sense.
I have a Lambda that uses MySQL RDS database on AWS and works fine locally when accessing the database on AWS. After successfully getting a JWT from an auth endpoint I try to hit the login endpoint and I get a 502 Bad Gateway. Using the CloudWatch logs I can trace the failure to right before the login query runs. I've confirmed that my MySQL config is correct and that I have a connection to the database. The lambda and the database are in the same region DB: us-east-1f, lambda: us-east-1.
I've confirmed the OPTIONS and POST request methods for this endpoint both are set up with CORS enabled in the API Gateway. I'm using my serverless.yml to set cors: true on all the endpoints even though I'm using app.use(cors()) in my index file.
The error message for the 502 is, {"message": "Internal server error"}
Here is the point of failure in my code:
'use strict';
const mysql = require('./index');
module.exports = {
loginSql: async (email, password) => {
// MAKES IT HERE AND THE PARAMS ARE CORRECT
try {
console.log('IN TRY %%%%%%%%%%%%%%');
// SEEMS TO DIE HERE
const results = await mysql.query({
sql: `SELECT
id, first_name, last_name, email
FROM users
WHERE email = ?
AND password = ?`,
timeout: 50000,
values: [email, password],
});
// NEVER MAKES IT HERE /////////
console.log('QUERY RAN %%%%%%%%%%%%');
mysql.end();
if (results.length < 1) return false;
return results;
} catch (error) {
// DOESN'T THROW ERROR
console.log('LOGIN DB ERROR', error);
throw new Error('LOGIN DB ERROR THROWN', error);
}
},
};
I just created the exact same use case in that I have a LAMBDA function written in Java querying data from a MySQL RDS instance. It works perfectly.
Here is your issue:
To connect to the RDS instance from a Lambda function, you must set the inbound rules using the same security group as the RDS Instance. For details, How do I configure a Lambda function to connect to an RDS instance?.

404 Error when making a POST request using fetch()

I am following this tutorial from Hakernoon to set up Node.js with MySQL using my machine as local server.
I am using a few different tools, but they don't seem to be a problem. I'm using:
Ubuntu 16.04
Node.js
MySQL Workbench (He uses Homebrew because his is a Mac)
MySQL
knex.js
Express
*(Ubuntu and Workbench are the only differences)
Summarizing,the whole tutorial works well except when I reach the part of 'Login'. Here, we build a form to enter the user name and password making a POST requests. Then, if everything is OK, it returns a 200 status, else shows a message saying the login failed. And here is the problems. Every time I try to log in (even when being sure the credentials are correct and knowing that that user is stored in the database) it tells me that the login fails.
Checking on the browser inspect tool, it shows a Fail to load resources: the server responded with a status of 404 (Not found). It also points out that the problems is in the fetch() function I use in my post function to make the POST requests.
I checked the documentation on fetch() but is does not clarify much. Also I tried to contact the author of the tutorial and I got no answer. What am I doing wrong with fetch to give me the 404 status?
Also, every time I create a new user (also a POST request), it does it with no problem and I can see it in the database in MySQLWorkbench.
This is the file (app.js) with the code to create users and login:
const CreateUser = document.querySelector('.CreateUser')
CreateUser.addEventListener('submit', (e) => {
e.preventDefault()
const username = CreateUser.querySelector('.username').value
const password = CreateUser.querySelector('.password').value
post('/createUser', { username, password })
})
const Login = document.querySelector('.Login')
Login.addEventListener('submit', (e) => {
e.preventDefault();
const username = Login.querySelector('.username').value
const password = Login.querySelector('.password').value
post('/login', {username, password})
.then(({status}) => {
if(status === 200)
alert('login success')
else
alert('login failed')
})
})
function post (path, data) {
return window.fetch(path, { <========= Here is where the browser shows the problem
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
}
***I am not posting the rest of the code to not make it too long, if more info is needed, let me know). Thanks!

web3.eth.accounts.create method doesn't actually create new account

I try to create an eth account via RPC in private network.
What I have done so far are:
launch geth node and create private network.
create simple javascript program using web3 1.0.0, typescript
run and get result as below but the account isn't created
Code:
const result = await web3.eth.personal.unlockAccount(senderId, senderPassword, duration)
if (result === true) {
// const newAccountResult = await web3.eth.personal.newAccount('password')
const newAccountResult = await web3.eth.accounts.create('user01')
console.log(newAccountResult)
}
Result:
web3.eth.accounts.create returns the following result
{ address: '0xf10105f862C1cB10550F4EeB38697308c7A290Fc',
privateKey: '0x5cba6b397fc8a96d006988388553ec17a000f7da9783d906979a2e1c482e7fcb',
signTransaction: [Function: signTransaction],
sign: [Function: sign],
encrypt: [Function: encrypt] }
But web3.eth.getAccounts method returns only 1 account.
[ '0xaf0034c41928Db81E570061c58c249f61CFF57f2' ]
Seems web3.eth.accounts.create method has succeeded as the result includes account address and private key.
But I don't understand why web3.eth.getAccounts method doesn't include the created account.
I also checked geth via console, the result is same.
> eth.accounts
["0xaf0034c41928db81e570061c58c249f61cff57f2"]
And eth.personal.newAccount didn't work.
Do I need to do something after web3.eth.accounts.create?
I appreciate any help.
If i got it right, web.eth.accounts.create is a way to create accounts without storing them on the local node, so its basically a way to get a valid keypair on-the-fly without storing anything on the keystore)
web3.eth.personal.newAccount() should be availabel if you have the personal-API activated on your geth node (which is default behavior for ganache, with geth you need to activate it via geth --dev/testnet --rpc --rpcapi eth,web3,personal (note: of course you should be very careful with allowing personal-API on mainnet, make sure that RPC access is restricted so only you/privileged users can access it)
(async () => {
let newAccount = await web3.eth.personal.newAccount();
console.log(newAccount);
let accounts = await web3.eth.getAccounts();
console.log(accounts);
})();
Should give something like
0xb71DCf0191E2B90efCD2638781DE40797895De66
[
...
'0xb71DCf0191E2B90efCD2638781DE40797895De66' ]
Refs https://medium.com/#andthentherewere0/should-i-use-web3-eth-accounts-or-web3-eth-personal-for-account-creation-15eded74d0eb