# secrets-manager-sdk-v3

Wrapper for AWS Secrets Manager (using AWS SDK for Node v3)

## Motivation

We introduced this package to reduce the friction when using the @theorchard/backend-m2m-token-manager with AWS SecretsManager.

- the M2MTokenManager uses a `SecretsManager` matching this [interface](https://github.com/theorchard/backend-js-packages/blob/a1477860af9426ec161ddb42988c478c1e971fd4/packages/backend-m2m-token-manager/src/interfaces/getSecret.ts#L1-L3).
- the `SecretsManager` class implements the interface

Also note that we chose to explicitly keep this wrapper/package focused on using AWS SDK for Node v3,
hence the `sdk-v3` in the naming of the package. This means that
if/when AWS releases a newer SDK for Node, a new wrapper/package should be introduced, instead of trying to
re-purpose this package.

## Setup

Follow this [guide](https://www.notion.so/Javascript-Package-Management-Setup-9553d5d491c94835aa787fdf0fc4838d) to get your environment set up to work with private packages.

Then, add/install the package:

```sh
npm add @theorchard/backend-secrets-manager-sdk-v3
```

You may note a warning indicating an unmet peer dependency. It will look something like:

```sh
"@theorchard/backend-secrets-manager-sdk-v3@x.y.z" has unmet peer dependency "@aws-sdk/client-secrets-manager@^3.x".
```

This means you should additionally add/install `@aws-sdk/client-secrets-manager`:

```sh
npm add @aws-sdk/client-secrets-manager
```

Please be sure to configure your AWS Credentials properly.

When using this locally, you may need to `awsume prod` (or whatever role you use).

## Usage

You can instantiate a SecretsManager singleton to re-use:

```ts
import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
import { SecretsManager } from "@theorchard/backend-secrets-manager-sdk-v3";

const secretsManager = new SecretsManager({
  secretsManagerClient: new SecretsManagerClient(),
});
```

Afterward, you can use the singleton to fetch a secret from AWS Secrets Manager. Please note that it needs the actual SecretId --
it will not build the SecretId using environment, service name, secret name, etc. on your behalf.

```ts
try {
  const secretString = await secretsManager.getSecret(
    // Returns a string or will throw an exception
    "qa/pdp-backfill/M2M_JWT_ACCESS_TOKEN",
  );
  console.log("secretString", secretString);
} catch (e) {
  console.log("secretString", e);
}
```

## Troubleshooting

### `CredentialsProviderError`

If you get an error like `CredentialsProviderError: Could not load credentials from any providers`, please check your AWS Credentials are configured/available to the application.

If you see this from a locally running application, you should run `awsume <role>`. See [AWS Access](https://www.notion.so/AWS-Access-f841b9dd815d4443a80e96a86c92cd2f) for more.
If you see this from running in Docker, you should ensure the following environment variables are passed in (usually from the local host's environment variables):

- AWS_ACCESS_KEY_ID
- AWS_DEFAULT_REGION=us-east-1
- AWS_SECRET_ACCESS_KEY
- AWS_SESSION_TOKEN

If you are using a `docker-compose.yml` file, you can ensure these are listed for the application, under `environment` stanza:

```yaml
  your-app:
    build:
      context: .
      target: deploy
    environment:
      - AWS_ACCESS_KEY_ID
      - AWS_DEFAULT_REGION=us-east-1
      - AWS_SECRET_ACCESS_KEY
      - AWS_SESSION_TOKEN
      ...
```

### `AccessDeniedException`

If you get an error like `AccessDeniedException: User: <some arn> is not authorized to perform: secretsmanager:GetSecretValue on resource: <secret id> because no identity-based policy allows the secretsmanager:GetSecretValue action`, please check that the secret id is correct AND that the assumed role actually has access to the secret.
