Skip to content

Commit

Permalink
Merge pull request #11 from Infisical/daniel/fix-imports
Browse files Browse the repository at this point in the history
feat(secrets): get secrets with imports
  • Loading branch information
DanielHougaard authored Jan 27, 2025
2 parents d7cd9b9 + 6ff584c commit 3d0bf80
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,33 @@ const allSecrets = await client.secrets().listSecrets({
**Returns:**
- `ApiV3SecretsRawGet200Response`: The response containing the list of secrets.

#### List secrets with imports

The `listSecretsWithImports` method makes it easier to get all your secrets at once. The imported secrets will automatically be added to the secrets returned. The secrets in the selected environment will take precedence over the imported secrets. This means if you have secrets with conflicting names, the secret from the environment the import was imported into, will take precedence.

```typescript
const allSecrets = await client.secrets().listSecretsWithImports({
environment: "dev",
projectId: "<your-project-id>",
expandSecretReferences: true,
recursive: false,
secretPath: "/foo/bar"
});
```

**Parameters:**
- `projectId` (string): The ID of your project.
- `environment` (string): The environment in which to list secrets (e.g., "dev").
- `secretPath` (str): The path to the secrets.
- `expandSecretReferences` (bool): Whether to expand secret references.
- `recursive` (bool): Whether to list secrets recursively.
- `tagFilters` (string[]): Tags to filter secrets.

**Returns:**
- `ApiV1DashboardSecretsOverviewGet200ResponseSecretsInner`: The response containing the list of secrets, with imports.



#### Create Secret

```typescript
Expand Down
39 changes: 38 additions & 1 deletion src/custom/secrets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
DefaultApiApiV3SecretsRawSecretNamePostRequest
} from "../infisicalapi_client";
import { newInfisicalError } from "./errors";
import { getUniqueSecretsByKey } from "./util";

type SecretType = "shared" | "personal";

Expand Down Expand Up @@ -51,7 +52,7 @@ export type UpdateSecretResult = ApiV3SecretsRawSecretNamePost200Response;
export type CreateSecretResult = ApiV3SecretsRawSecretNamePost200Response;
export type DeleteSecretResult = ApiV3SecretsRawSecretNamePost200Response;

const convertBool = (value: boolean | undefined) => (value ? "true" : "false");
const convertBool = (value?: boolean) => (value ? "true" : "false");

export default class SecretsClient {
#apiInstance: InfisicalApi;
Expand Down Expand Up @@ -81,6 +82,42 @@ export default class SecretsClient {
}
};

listSecretsWithImports = async (options: Omit<ListSecretsOptions, "includeImports">): Promise<ListSecretsResult["secrets"]> => {
const res = await this.listSecrets({
...options,
includeImports: true
});

let { imports, secrets } = res;
if (imports) {
if (options.recursive) {
secrets = getUniqueSecretsByKey(secrets);
}

for (const imp of imports) {
for (const importedSecret of imp.secrets) {
// CASE: We need to ensure that the imported values don't override the "base" secrets.
// Priority order is:
// Local/Preset variables -> Actual secrets -> Imported secrets (high->low)

// Check if the secret already exists in the secrets list
if (!secrets.find(s => s.secretKey === importedSecret.secretKey)) {
secrets.push({
...importedSecret,
secretPath: imp.secretPath,
// These fields are not returned by the API
updatedAt: new Date().toISOString(),
createdAt: new Date().toISOString(),
tags: []
});
}
}
}
}

return secrets;
};

getSecret = async (options: GetSecretOptions): Promise<GetSecretResult> => {
try {
const res = await this.#apiInstance.apiV3SecretsRawSecretNameGet(
Expand Down
13 changes: 13 additions & 0 deletions src/custom/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ import axios from "axios";
import { AWS_IDENTITY_DOCUMENT_URI, AWS_TOKEN_METADATA_URI } from "./constants";
import AWS from "aws-sdk";
import { InfisicalSDKError } from "./errors";
import { ApiV3SecretsRawGet200Response } from "../infisicalapi_client";

type Secret = ApiV3SecretsRawGet200Response["secrets"][number];

export const getUniqueSecretsByKey = (secrets: Secret[]) => {
const secretMap = new Map<string, Secret>();

for (const secret of secrets) {
secretMap.set(secret.secretKey, secret);
}

return Array.from(secretMap.values());
};

export const getAwsRegion = async () => {
const region = process.env.AWS_REGION; // Typically found in lambda runtime environment
Expand Down

0 comments on commit 3d0bf80

Please sign in to comment.