Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type checking error with fromEnv in @aws-sdk/credential-providers #3392

Open
sudhirjena opened this issue Mar 3, 2022 · 29 comments
Open

type checking error with fromEnv in @aws-sdk/credential-providers #3392

sudhirjena opened this issue Mar 3, 2022 · 29 comments
Labels
guidance General information and guidance, answers to FAQs, or recommended best practices/resources. p2 This is a standard priority issue

Comments

@sudhirjena
Copy link

sudhirjena commented Mar 3, 2022

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/credential-providers@3.53.0

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 or npm 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";
@sudhirjena sudhirjena added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Mar 3, 2022
@sekamaneka
Copy link

i also face the same problem

@justenau
Copy link

justenau commented Mar 9, 2022

Receiving the same error but for fromIni as well

@JuanUmbarila-engooden
Copy link

Has anyone found a way to fix it? I have the same problem with fromIni

@justenau
Copy link

justenau commented Mar 11, 2022

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 :/

@JuanUmbarila-engooden
Copy link

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 :/

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

@stuartmccoll
Copy link

stuartmccoll commented Apr 6, 2022

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?

@trivikr
Copy link
Member

trivikr commented Apr 29, 2022

Assigning to @ajredniwja for triaging.

@trivikr
Copy link
Member

trivikr commented Apr 29, 2022

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?

@diehbria
Copy link

diehbria commented May 2, 2022

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.

@trivikr
Copy link
Member

trivikr commented May 3, 2022

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 #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.

@diehbria
Copy link

diehbria commented May 3, 2022

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:

@trivikr
Copy link
Member

trivikr commented May 6, 2022

  • 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.

@trivikr trivikr added guidance General information and guidance, answers to FAQs, or recommended best practices/resources. and removed needs-triage This issue or PR still needs to be triaged. bug This issue is a bug. labels May 6, 2022
@trivikr
Copy link
Member

trivikr commented May 6, 2022

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?

@trivikr
Copy link
Member

trivikr commented May 6, 2022

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).

@diehbria
Copy link

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

@evanottinger
Copy link

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?

@RanVaknin RanVaknin added the p2 This is a standard priority issue label Mar 15, 2023
@alamberti
Copy link

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.

@ecarrell
Copy link

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.

@yongzhang
Copy link

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.

@jayPatel222
Copy link

Any update on this?

@theSJace
Copy link

theSJace commented Jan 9, 2024

I am also facing the same issue, appreciate any updates on the matter.

@jinglongwu
Copy link

same, getting a fromIni is not a function

@marc-at
Copy link

marc-at commented Jan 26, 2024

Any workarounds for this?

@jfoxx-aperia
Copy link

any update for this?

@kuhe
Copy link
Contributor

kuhe commented Mar 1, 2024

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

@jove4015
Copy link

@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?

@kuhe
Copy link
Contributor

kuhe commented Mar 18, 2024

@jove4015 please create a new issue with instructions on how to replicate the error.

@mikekinlock
Copy link

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.

@rforster-dev
Copy link

rforster-dev commented Apr 17, 2024

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
guidance General information and guidance, answers to FAQs, or recommended best practices/resources. p2 This is a standard priority issue
Projects
None yet
Development

No branches or pull requests