feat: allow to override vault secret engine in entity level

Signed-off-by: Ilya Katlinski <ilya.katlinsky@gmail.com>
This commit is contained in:
Ilya Katlinski
2023-08-08 08:59:15 +02:00
parent 7b8c703602
commit 49c3657ac6
7 changed files with 84 additions and 18 deletions
+17 -1
View File
@@ -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
![Screenshot of the vault plugin with missing annotation](images/annotation-missing.png)
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
+15 -3
View File
@@ -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[] = [
+1
View File
@@ -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';