aws-sdk-js-v3
aws-sdk-js-v3 copied to clipboard
type checking error with `fromEnv` in @aws-sdk/credential-providers
Describe the bug
While using @aws-sdk/credential-providers
in a React typescript application having the following code:
import { initialize } from "@iot-app-kit/source-iotsitewise";
import { fromEnv } from "@aws-sdk/credential-providers";
const { query } = initialize({
awsCredentials: fromEnv(),
awsRegion: "us-east-1",
});
We encounter the following build error:
ERROR in ./src/App.tsx 16:18-25
export 'fromEnv' (imported as 'fromEnv') was not found in '@aws-sdk/credential-providers' (possible exports: fromCognitoIdentity, fromCognitoIdentityPool, fromTemporaryCredentials, fromWebToken)
Your environment
macOS
SDK version number
@aws-sdk/[email protected]
Is the issue in the browser/Node.js/ReactNative?
Browser
Details of the browser/Node.js/ReactNative version
Browsers:
Chrome: 98.0.4758.109
Firefox: 91.6.0
Safari: 15.3
Steps to reproduce
Please share code or minimal repo, and steps to reproduce the behavior.
- Create a new ReactJS application
npx create-react-app my-app --template typescript
- Install minimal packages to reproduce issue
npm install @aws-sdk/credential-providers @iot-app-kit/source-iotsitewise
- Add following code to
App.tsx
import { initialize } from '@iot-app-kit/source-iotsitewise';
import { fromEnv } from '@aws-sdk/credential-providers';
const { query } = initialize({ awsCredentials: fromEnv(), awsRegion: 'us-east-1' });
- Either run
npm start
ornpm run build
Observed behavior
React app fails to run or build due to following type checking error
ERROR in ./src/App.tsx 16:18-25
export 'fromEnv' (imported as 'fromEnv') was not found in '@aws-sdk/credential-providers' (possible exports: fromCognitoIdentity, fromCognitoIdentityPool, fromTemporaryCredentials, fromWebToken)
Expected behavior
Although @aws-sdk/credential-providers has the following exported member, the type resolution fails. The type resolution for fromEnv
should not fail.
export * from "./fromCognitoIdentity";
export * from "./fromCognitoIdentityPool";
export * from "./fromContainerMetadata";
export * from "./fromEnv";
export * from "./fromIni";
export * from "./fromInstanceMetadata";
export * from "./fromProcess";
export * from "./fromSSO";
export * from "./fromTemporaryCredentials";
export * from "./fromTokenFile";
export * from "./fromWebToken";
i also face the same problem
Receiving the same error but for fromIni
as well
Has anyone found a way to fix it? I have the same problem with fromIni
One strange workaround that worked for me after a lot of experimenting was using version 3.40 of this package and importing fromIni
with require
statement instead of the usual import (even though my project is with es6)
const { fromIni } = require("@aws-sdk/credential-providers");
Though that did not work with forEnv
and this workaround doesn't solve the initial problem there is on the newest version :/
One strange workaround that worked for me after a lot of experimenting was using version 3.40 of this package and importing
fromIni
withrequire
statement instead of the usual import (even though my project is with es6)const { fromIni } = require("@aws-sdk/credential-providers");
Though that did not work with
forEnv
and this workaround doesn't solve the initial problem there is on the newest version :/
Thank you for you reply!!!
I made that change in the code but when I call fromIni
it still does not recognize it.
fromIni is not a function
It's a strange behavior of the library
Has anybody been able to resolve this?
I'm hitting the same issue with fromIni
in v3.58.0
.
import { fromIni } from "@aws-sdk/credential-providers";
The following error is raised:
export 'fromIni' (imported as 'fromIni') was not found in '@aws-sdk/credential-providers' (possible exports: fromCognitoIdentity, fromCognitoIdentityPool, fromTemporaryCredentials, fromWebToken)
Looking at index.web.ts
, the exports match those returned in the above error message:
export * from "./fromCognitoIdentity";
export * from "./fromCognitoIdentityPool";
export * from "./fromTemporaryCredentials";
export * from "./fromWebToken";
Do additional exports need to be added here to match those within index.ts
?
Assigning to @ajredniwja for triaging.
We don't export fromEnv
in browser environments, as they don't have an environment to read variables from.
Similar use case for fromIni
which reads from configuration files, which do not exist in browser environments.
For a browser application, you need to use one of the following credential providers: fromCognitoIdentity, fromCognitoIdentityPool, fromTemporaryCredentials, fromWebToken
@sudhirjena @justenau Can you explain you use case where you plan to read credentials from environment or configuration files in the browser? If you're using server side rendering in your React application, does any configuration need to be set to use Node.js code from dependencies?
It is incorrect to say that fromEnv
wouldn't work in the browser environment, it is common for environment variables to be placed into process.env
via build processes. The use case is for local development work flows - it is a huge burden to users of software to need to figure out how to set up something such as IAM to get a 'hello world' working.
Due to security concerns, it is highly recommended against guiding people towards hard coding strings directly into their code bases. Within Amazon, we are actually strictly forbidden from even suggesting this within our example repositories or code samples.
For this reason we need a good path forward on these local development use cases.
Additionally, for any credential-providers which are intentionally not supported in the browser, they should be:
- documented (of which these omissions are not)
- throw an error, with an intelligible message, rather than simply being omitted from the bundles which causes lots of confusion.
it is common for environment variables to be placed into
process.env
via build processes
Can you share an example or documentation of how it's done in case of create react app? I'm wondering if it's specific to React or CRA or used extensively in frontend ecosystem.
- documented (of which these omissions are not)
I created a feature request to add documentation at https://github.com/aws/aws-sdk-js-v3/issues/3586
- throw an error, with an intelligible message, rather than simply being omitted from the bundles which causes lots of confusion.
The existing error clearly mentions fromEnv
is not exported for browser environment. The users shouldn't try to import credential provider not available in their environment.
The existing error clearly mentions fromEnv is not exported for browser environment. The users shouldn't try to import credential provider not available in their environment.
Which is not documented, and clearly many people think this is an accidental bug, as evident by this ticket. This method of communicating the API is not a good design, because the library still exports them as typescript types.
Environment variables in the front end:
- https://create-react-app.dev/docs/adding-custom-environment-variables/
- https://www.npmjs.com/package/rollup-plugin-inject-process-env
- https://webpack.js.org/plugins/environment-plugin/
this is not a CRA specific thing, every modern front-end build system has ability to inject
process.env
. It's used commonly for local development configurations.
- create-react-app.dev/docs/adding-custom-environment-variables
This wiki clearly mentions
WARNING: Do not store any secrets (such as private API keys) in your React app!
It's not explicitly called out in homepage of rollup and webpack plugins, the SDK shouldn't expose fromEnv
for frontend which would encourage users to do something which is not a standard. Although injecting process.env
is supported by CRA directly, and in rollup and webpack through plugins - it's not a browser standard to have environment variables in the frontend.
If we officially expose fromEnv
in the frontend, users may prefer it over frontend specific standard credential providers fromCognitoIdentity, fromCognitoIdentityPool, fromTemporaryCredentials and fromWebToken.
Here's the workaround to explicitly set credentials if you're injecting them through process.env
const client = new ClientName({
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
})
This explicit code during client creation will ensure that it's not recommended by the SDK. I'm marking this issue as guidance.
It's used commonly for local development configurations.
Out of curiosity to check if any follow-up is required from SDK: How do frontend developers ensure that environment variables are removed when pushing to production?
Another question: Would it be helpful is SDK provides a different utility to improve local development experience for frontend? If yes, what that utility should look like?
We can create a new feature request for this utility. I'm assuming this utility (say @aws-sdk/util-frontend
) will work only in local environment (like when NODE_ENV=dev
in case of environment variables).
If the decision is made not to include these, I think it should be considered to have the credential providers throw errors at run time which point towards the documentation and explain these aren't supported.
The message "export 'fromEnv' (imported as 'fromEnv') was not found in '@aws-sdk/credential-providers" leads the user to think it's an issue with the SDK, as we can see by the comments made in the issue. The typescript definitions also indicate it should exist, making for a confusing experience.
My use case for fromEnv
is to write documentation for users of my teams library for simple setup - fromEnv
for us would allow us to give people a way to simply set up without copying and pasting credentials into their library, without us writing confusing documentation around implementing their own credential provider or instantiating multiple SDKs with process env variables
I have just encountered this same issue. I don't really understand the logic of not including fromEnv / fromProcess / fromIni in the exports for the browser version.
How do frontend developers ensure that environment variables are removed when pushing to production?
Using AWS, we can inject secrets into the environment of containerized applications at runtime. This is even the recommended practice with ECS according to the documentation. We can also make the environmental variables accessible from containers by mapping the environmental variables of an EC2 from EB to the container using docker-compose according to the EB developer's guide. It's not a stretch to use an entrypoint script in a container to retrieve the secrets from the environment (as described in the documentation) and place them in a credentials file which the React application can access.
I would also like to emphasize @diehbria 's comment:
If the decision is made not to include these, I think it should be considered to have the credential providers throw errors at run time which point towards the documentation and explain these aren't supported.
My question then becomes, what is the recommendation from AWS if we're not able to import fromEnv / fromProcess / fromIni in a containerized React application?
I believe I am having a related issue, though through the lens of NextJS. In a getServerSideProps
call which executes in a nodejs runtime:
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
import { fromIni } from '@aws-sdk/credential-providers';
const ddbClient = new DynamoDBClient({
credentials: fromIni({
profile: 'saml',
}),
region,
});
allows me to successfully use a GetCommand
to retrieve data, on the server, but then my locally running environment throws TypeError: (0 , _aws_sdk_credential_providers__WEBPACK_IMPORTED_MODULE_2__.fromIni) is not a function
in the client.
I then tried to use the node credential provider:
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
import { defaultProvider } from '@aws-sdk/credential-provider-node';
const provider = defaultProvider({
profile: 'saml',
});
const ddbClient = new DynamoDBClient({
credentialDefaultProvider: provider,
region,
});
and encounter an error:
./node_modules/@aws-sdk/credential-provider-node/node_modules/@aws-sdk/credential-provider-process/dist-es/resolveProcessCredentials.js:2:0
Module not found: Can't resolve 'child_process'
I could not find anything explaining when to use which module, why they are different (when they seem to do the same thing), or these errors.
It sounds like typeError is because fromIni
is being excluded from the webpack bundle (which is not document and not obvious as others have said). So i should be using the node version, but following the example, everything fails and there is no other documentation to help resolve it.
Any update on this? I too am needing to use saml2aws creds with fromIni in a Vue app. I'm getting the "Syntax Error: ambiguous indirect export: fromIni" error message. I've followed the code instructions from the latest AWS SDK version 3 documentation for credential-providers.
I have the same issue in local development, I got
No matching export in "node_modules/@aws-sdk/credential-providers/dist-es/index.browser.js" for import "fromIni"
Now I'm stuck on this.
Any update on this?
I am also facing the same issue, appreciate any updates on the matter.
same, getting a fromIni is not a function
Any workarounds for this?
any update for this?
fromEnv
will not be provided in the browser, since process
is a Node.js global and to use it would mean leaving credentials readable in an easily discoverable global object, vulnerable to 3rd party scripts.
Webpack may transform the Node.js process env to the application, but this is only a simulated effect and additionally not consistent across bundlers.
Any credential supplying async function can be provided to an SDK client. It will be called automatically when credentials are needed and when they expire (if expiration is set).
import { S3Client } from "@aws-sdk/client-s3";
const provider = async () => {
return {
accessKeyId: "...",
secretAccessKey: "...",
sessionToken: "...",
expiration: new Date( /*...*/ )
}
};
new S3Client({
credentials: provider
});
If you really want to use process.env
, write the provider
function in such a way that it reads from your simulated process.env
. This is identical to the SDK's Node.js fromEnv
function, but the key difference is we do not recommend it, and therefore don't provide it.
As documented here: https://www.npmjs.com/package/@aws-sdk/credential-providers
The following providers are not available in the browser:
fromContainerMetadata
, fromInstanceMetadata
, fromEnv
, fromIni
, fromNodeProviderChain
, fromProcess
, fromSSO
, fromTokenFile
@kuhe Not sure if this comment was directed at everyone or some other poster... In our situation, we are not trying to use AWS from the browser at all (we don't provide any credentials there). We are trying to pass container credentials to our TRPC server and we are getting these warnings. They are new and large warnings that didn't use to be there. The warnings really don't apply to us at all. We would like to be rid of them. Is there some way to restrict this warning just to cases where someone is trying to use these in the browser?
@jove4015 please create a new issue with instructions on how to replicate the error.
Hey there,
the last two days I was working on a vue application and faced the same problem, whereby the mentioned solution of kuhe worked. After having it working I took myself some time to re-think things and the point is that Vue, React, ect. are frontend frameworks which are made to create an application for the browser, meaning they show all their information in the code. Now out of security perspective it makes sense that these functions aren't available for frontend applications which are running in the browser, because there is the risk to show the credentials in the code.
In my case I'll have a lambda in between the application to handle the s3 authentication as well as the up- and download of objects, which then will be passed to the FE-App. Another way how to handle it, would be to make the S3 bucket public and work with resource permissions and CORS rules to make sure that the traffic is safe.
I have a similar issue with using fromNodeProviderChain
in a nextjs project.
We use process.envs to determine whether to fetch a public lambda for development or a private lambda (which is what is on our production sites) which is what is utilizing this.
Locally this causes an issue when we build nextjs packages unless I change it to CJS syntax for the import.
Most noticably, this error is incorrect; as its not so much that its a bad import reference, just that it isn't designed to be used in this way (even though, it works in the way that it is being used by everyone in this thread).