feat: allow to override vault secret engine in entity level
Signed-off-by: Ilya Katlinski <ilya.katlinsky@gmail.com>
This commit is contained in:
+17
-1
@@ -42,7 +42,7 @@ To get started, first you need a running instance of Vault. You can follow [this
|
||||
vault:
|
||||
baseUrl: http://your-vault-url
|
||||
token: <VAULT_TOKEN>
|
||||
secretEngine: 'customSecretEngine' # Optional. By default it uses 'secrets'
|
||||
secretEngine: 'customSecretEngine' # Optional. By default it uses 'secrets'. Can be overwritten by the annotation of the entity
|
||||
kvVersion: <kv-version> # Optional. The K/V version that your instance is using. The available options are '1' or '2'
|
||||
```
|
||||
|
||||
@@ -67,6 +67,7 @@ metadata:
|
||||
# ...
|
||||
annotations:
|
||||
vault.io/secrets-path: path/to/secrets
|
||||
vault.io/secret-engine: customSecretEngine # Optional. By default it uses 'secertEngine' value from configuration.
|
||||
```
|
||||
|
||||
The path is relative to your secrets engine folder. So if you want to get the secrets for backstage and you have the following directory structure:
|
||||
@@ -86,9 +87,24 @@ If the annotation is missing for a certain component, then the card will show so
|
||||
|
||||

|
||||
|
||||
In case you need to support different secret engines for entities of the catalog you can proivde optional annotion to the entity in `catalog-info.yaml`:
|
||||
|
||||
```diff
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Component
|
||||
metadata:
|
||||
# ...
|
||||
annotations:
|
||||
vault.io/secrets-path: path/to/secrets
|
||||
+ vault.io/secret-engine: customSecretEngine # Optional. By default it uses 'secertEngine' value from configuration.
|
||||
```
|
||||
|
||||
That will overwrite the default secret engine from the configuration.
|
||||
|
||||
## Features
|
||||
|
||||
- List the secrets present in a certain path
|
||||
- Use different secret engines for different components
|
||||
- Open a link to view the secret
|
||||
- Open a link to edit the secret
|
||||
- Renew the token automatically with a defined periodicity
|
||||
|
||||
@@ -46,8 +46,12 @@ export interface VaultApi {
|
||||
/**
|
||||
* Returns a list of secrets used to show in a table.
|
||||
* @param secretPath - The path where the secrets are stored in Vault
|
||||
* @param secretMount - The mount point of the secrets engine, optional, overrides default secret engine
|
||||
*/
|
||||
listSecrets(secretPath: string): Promise<VaultSecret[]>;
|
||||
listSecrets(
|
||||
secretPath: string,
|
||||
secretMount?: string | undefined,
|
||||
): Promise<VaultSecret[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,10 +94,18 @@ export class VaultClient implements VaultApi {
|
||||
throw await ResponseError.fromResponse(response);
|
||||
}
|
||||
|
||||
async listSecrets(secretPath: string): Promise<VaultSecret[]> {
|
||||
async listSecrets(
|
||||
secretPath: string,
|
||||
secretMount?: string | undefined,
|
||||
): Promise<VaultSecret[]> {
|
||||
const query: { [key in string]: any } = {};
|
||||
if (secretMount) {
|
||||
query.engine = secretMount;
|
||||
}
|
||||
|
||||
const result = await this.callApi<{ items: VaultSecret[] }>(
|
||||
`v1/secrets/${encodeURIComponent(secretPath)}`,
|
||||
{},
|
||||
query,
|
||||
);
|
||||
return result.items;
|
||||
}
|
||||
|
||||
@@ -23,27 +23,33 @@ import Visibility from '@material-ui/icons/Visibility';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { VaultSecret, vaultApiRef } from '../../api';
|
||||
import { VAULT_SECRET_PATH_ANNOTATION } from '../../constants';
|
||||
import {
|
||||
VAULT_SECRET_ENGINE_ANNOTATION,
|
||||
VAULT_SECRET_PATH_ANNOTATION,
|
||||
} from '../../constants';
|
||||
|
||||
export const vaultSecretPath = (entity: Entity) => {
|
||||
export const vaultSecretConfig = (entity: Entity) => {
|
||||
const secretPath =
|
||||
entity.metadata.annotations?.[VAULT_SECRET_PATH_ANNOTATION];
|
||||
const secretEngine =
|
||||
entity.metadata.annotations?.[VAULT_SECRET_ENGINE_ANNOTATION];
|
||||
|
||||
return { secretPath };
|
||||
return { secretPath, secretEngine };
|
||||
};
|
||||
|
||||
export const EntityVaultTable = ({ entity }: { entity: Entity }) => {
|
||||
const vaultApi = useApi(vaultApiRef);
|
||||
const { secretPath } = vaultSecretPath(entity);
|
||||
const { secretPath, secretEngine } = vaultSecretConfig(entity);
|
||||
if (!secretPath) {
|
||||
throw Error(
|
||||
`The secret path is undefined. Please, define the annotation ${VAULT_SECRET_PATH_ANNOTATION}`,
|
||||
);
|
||||
}
|
||||
|
||||
const { value, loading, error } = useAsync(async (): Promise<
|
||||
VaultSecret[]
|
||||
> => {
|
||||
return vaultApi.listSecrets(secretPath);
|
||||
return vaultApi.listSecrets(secretPath, secretEngine);
|
||||
}, []);
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const VAULT_SECRET_ENGINE_ANNOTATION = 'vault.io/secrets-engine';
|
||||
export const VAULT_SECRET_PATH_ANNOTATION = 'vault.io/secrets-path';
|
||||
|
||||
Reference in New Issue
Block a user