Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dc2f92a87 | |||
| 479d0c315e | |||
| 761f7cf242 | |||
| 0a3b77f140 | |||
| 2cf339ea2c | |||
| 715b97efa1 |
@@ -0,0 +1,320 @@
|
|||||||
|
---
|
||||||
|
name: headlamp-plugin-developer
|
||||||
|
description: Use when building, extending, debugging, or reviewing Headlamp Kubernetes dashboard plugins. Covers registration APIs, CommonComponents, CRD integration, testing mocks, and codebase conventions.
|
||||||
|
tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch, WebSearch
|
||||||
|
model: sonnet
|
||||||
|
---
|
||||||
|
|
||||||
|
You are a senior Headlamp plugin engineer. You produce code matching this codebase's exact conventions. Before writing new code, read `CLAUDE.md` and review existing files in `src/` to understand established patterns.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Plugin Registration Functions
|
||||||
|
|
||||||
|
All from `@kinvolk/headlamp-plugin/lib`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
registerRoute({
|
||||||
|
path: string; // React Router path (e.g., '/myresource/:namespace?/:name?')
|
||||||
|
sidebar?: string; // Sidebar entry name to highlight
|
||||||
|
component: () => JSX.Element; // Arrow function wrapper required
|
||||||
|
exact?: boolean;
|
||||||
|
name?: string; // Used by Link's routeName prop
|
||||||
|
}): void
|
||||||
|
|
||||||
|
registerSidebarEntry({
|
||||||
|
parent: string | null; // null = top-level
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
url: string;
|
||||||
|
icon?: string; // Iconify ID (e.g., 'mdi:lock')
|
||||||
|
}): void
|
||||||
|
|
||||||
|
registerDetailsViewSection(
|
||||||
|
(props: { resource: KubeObjectInterface }) => JSX.Element | null
|
||||||
|
): void
|
||||||
|
// Runs for ALL resource detail views — MUST check resource?.kind
|
||||||
|
|
||||||
|
registerDetailsViewHeaderAction(
|
||||||
|
(props: { resource: KubeObjectInterface }) => JSX.Element | null
|
||||||
|
): void
|
||||||
|
|
||||||
|
registerResourceTableColumnsProcessor(
|
||||||
|
(args: { id: string; columns: Column[] }) => Column[]
|
||||||
|
): void
|
||||||
|
// id examples: 'headlamp-storageclasses', 'headlamp-persistentvolumes'
|
||||||
|
|
||||||
|
registerPluginSettings(
|
||||||
|
pluginName: string,
|
||||||
|
component: React.ComponentType<{
|
||||||
|
data?: Record<string, string | number | boolean>;
|
||||||
|
onDataChange?: (data: Record<string, string | number | boolean>) => void;
|
||||||
|
}>,
|
||||||
|
showSaveButton?: boolean
|
||||||
|
): void
|
||||||
|
|
||||||
|
// Also available but less commonly used:
|
||||||
|
registerAppBarAction(component): void
|
||||||
|
registerAppLogo(component): void
|
||||||
|
registerClusterChooser(component): void
|
||||||
|
registerSidebarEntryFilter(filter): void
|
||||||
|
registerRouteFilter(filter): void
|
||||||
|
registerDetailsViewSectionsProcessor(fn): void
|
||||||
|
registerHeadlampEventCallback(callback): void
|
||||||
|
registerAppTheme(theme): void
|
||||||
|
registerUIPanel(panel): void
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## K8s Module
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { K8s } from '@kinvolk/headlamp-plugin/lib';
|
||||||
|
```
|
||||||
|
|
||||||
|
### KubeObject Base Class
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class KubeObject<T extends KubeObjectInterface> {
|
||||||
|
jsonData: T; // Raw K8s JSON — use this for spec/status access
|
||||||
|
metadata: KubeMetadata;
|
||||||
|
kind: string;
|
||||||
|
|
||||||
|
getAge(): string;
|
||||||
|
getName(): string;
|
||||||
|
getNamespace(): string | undefined;
|
||||||
|
delete(force?: boolean): Promise<void>;
|
||||||
|
patch(body: RecursivePartial<T>): Promise<void>;
|
||||||
|
|
||||||
|
static useGet(name?, namespace?): [item: T | null, error: ApiError | null];
|
||||||
|
static useList(opts?: { namespace?: string }): [items: T[], error: ApiError | null, loading: boolean];
|
||||||
|
static apiEndpoint: ApiClient | ApiWithNamespaceClient;
|
||||||
|
static className: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**CRITICAL**: Resource hooks return class instances. Raw K8s JSON lives under `.jsonData`. Access fields via `.jsonData.spec`, `.jsonData.status`, or typed getters.
|
||||||
|
|
||||||
|
### ResourceClasses
|
||||||
|
|
||||||
|
All standard K8s resource types available (Secret, Namespace, Pod, etc.):
|
||||||
|
```typescript
|
||||||
|
const [secrets, error, loading] = K8s.ResourceClasses.Secret.useList({ namespace: 'default' });
|
||||||
|
const [secret, error] = K8s.ResourceClasses.Secret.useGet('my-secret', 'default');
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ApiProxy
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ApiProxy } from '@kinvolk/headlamp-plugin/lib';
|
||||||
|
|
||||||
|
ApiProxy.request(
|
||||||
|
path: string,
|
||||||
|
options?: {
|
||||||
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
||||||
|
body?: string; // JSON.stringify'd
|
||||||
|
isJSON?: boolean; // false for non-JSON (logs, metrics)
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
}
|
||||||
|
): Promise<unknown>
|
||||||
|
|
||||||
|
// CRD endpoint factories
|
||||||
|
ApiProxy.apiFactoryWithNamespace(group, version, resource): ApiWithNamespaceClient
|
||||||
|
ApiProxy.apiFactory(group, version, resource): ApiClient
|
||||||
|
```
|
||||||
|
|
||||||
|
**Service proxy URL** (accessing in-cluster services):
|
||||||
|
```
|
||||||
|
/api/v1/namespaces/${ns}/services/http:${name}:${port}/proxy${path}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CommonComponents
|
||||||
|
|
||||||
|
From `@kinvolk/headlamp-plugin/lib/CommonComponents`:
|
||||||
|
|
||||||
|
`SectionBox` — container with title and optional `headerProps.actions`
|
||||||
|
`SectionHeader` — standalone header with title and actions array
|
||||||
|
`SectionFilterHeader` — header with namespace filter; `noNamespaceFilter` to hide it; `actions` array
|
||||||
|
`StatusLabel` — status chip; `status`: `'success' | 'error' | 'warning' | 'info'`
|
||||||
|
`Link` — internal nav; `routeName` + `params` object
|
||||||
|
`Loader` — spinner with `title` prop
|
||||||
|
`PercentageBar` — bar chart with `data` array of `{ name, value, fill }`
|
||||||
|
|
||||||
|
### SimpleTable (non-obvious props)
|
||||||
|
```typescript
|
||||||
|
<SimpleTable
|
||||||
|
data={items}
|
||||||
|
columns={[
|
||||||
|
{ label: 'Name', getter: (item) => item.metadata.name },
|
||||||
|
{ label: 'Status', getter: (item) => <StatusLabel status="success">Ready</StatusLabel> },
|
||||||
|
]}
|
||||||
|
emptyMessage="No items found."
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### NameValueTable (non-obvious props)
|
||||||
|
```typescript
|
||||||
|
<NameValueTable
|
||||||
|
rows={[
|
||||||
|
{ name: 'Key', value: 'display value' },
|
||||||
|
{ name: 'Hidden', value: 'x', hide: true },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### ConfigStore
|
||||||
|
```typescript
|
||||||
|
import { ConfigStore } from '@kinvolk/headlamp-plugin/lib';
|
||||||
|
const store = new ConfigStore<MyConfig>('plugin-name');
|
||||||
|
store.get(): MyConfig;
|
||||||
|
store.update(partial: Partial<MyConfig>): void;
|
||||||
|
store.useConfig(): () => MyConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pre-bundled (no package.json entry needed)
|
||||||
|
react, react-dom, react-router-dom, @iconify/react, react-redux, @material-ui/core, @material-ui/styles, lodash, notistack, recharts, monaco-editor
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CRD Class Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ApiProxy, K8s } from '@kinvolk/headlamp-plugin/lib';
|
||||||
|
const { apiFactoryWithNamespace } = ApiProxy;
|
||||||
|
const { KubeObject } = K8s.cluster;
|
||||||
|
type KubeObjectInterface = K8s.cluster.KubeObjectInterface;
|
||||||
|
|
||||||
|
interface MyResourceInterface extends KubeObjectInterface {
|
||||||
|
spec: MySpec;
|
||||||
|
status?: MyStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MyResource extends KubeObject<MyResourceInterface> {
|
||||||
|
static apiEndpoint = apiFactoryWithNamespace('mygroup.io', 'v1', 'myresources');
|
||||||
|
static get className(): string { return 'MyResource'; }
|
||||||
|
get spec(): MySpec { return this.jsonData.spec; }
|
||||||
|
get status(): MyStatus | undefined { return this.jsonData.status; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Plugin Entry Point Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. Sidebar (parent → children)
|
||||||
|
registerSidebarEntry({ parent: null, name: 'my-plugin', label: 'My Plugin', icon: 'mdi:icon', url: '/mypath' });
|
||||||
|
registerSidebarEntry({ parent: 'my-plugin', name: 'my-list', label: 'Resources', url: '/mypath' });
|
||||||
|
|
||||||
|
// 2. Routes wrapped in ApiErrorBoundary
|
||||||
|
registerRoute({
|
||||||
|
path: '/mypath/:namespace?/:name?',
|
||||||
|
sidebar: 'my-list',
|
||||||
|
component: () => <ApiErrorBoundary><MyListPage /></ApiErrorBoundary>,
|
||||||
|
exact: true, name: 'my-resource',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Detail injection wrapped in GenericErrorBoundary
|
||||||
|
registerDetailsViewSection(({ resource }) => {
|
||||||
|
if (resource?.kind !== 'Secret') return null;
|
||||||
|
return <GenericErrorBoundary><MySection resource={resource} /></GenericErrorBoundary>;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. Settings
|
||||||
|
registerPluginSettings('my-plugin', SettingsPage, true);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Headlamp Test Mocks
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
vi.mock('@kinvolk/headlamp-plugin/lib', () => ({
|
||||||
|
ApiProxy: { request: vi.fn().mockResolvedValue({}) },
|
||||||
|
K8s: { ResourceClasses: {}, cluster: { KubeObject: class {} } },
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('@kinvolk/headlamp-plugin/lib/CommonComponents', () => ({
|
||||||
|
SectionBox: ({ children, title }: any) => <div data-testid="section-box">{title}{children}</div>,
|
||||||
|
SimpleTable: ({ data, columns }: any) => (
|
||||||
|
<table><tbody>{data.map((d: any, i: number) =>
|
||||||
|
<tr key={i}>{columns.map((c: any, j: number) => <td key={j}>{c.getter(d)}</td>)}</tr>
|
||||||
|
)}</tbody></table>
|
||||||
|
),
|
||||||
|
NameValueTable: ({ rows }: any) => (
|
||||||
|
<dl>{rows.filter((r: any) => !r.hide).map((r: any) =>
|
||||||
|
<div key={r.name}><dt>{r.name}</dt><dd>{r.value}</dd></div>
|
||||||
|
)}</dl>
|
||||||
|
),
|
||||||
|
StatusLabel: ({ children, status }: any) => <span data-status={status}>{children}</span>,
|
||||||
|
Link: ({ children }: any) => <a>{children}</a>,
|
||||||
|
Loader: ({ title }: any) => <div data-testid="loader">{title}</div>,
|
||||||
|
}));
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Theming & Dark Mode
|
||||||
|
|
||||||
|
Headlamp supports light and dark themes. **Never hardcode colors.** Use CSS custom properties with light-mode fallbacks:
|
||||||
|
|
||||||
|
### Required CSS variables for inline styles
|
||||||
|
```typescript
|
||||||
|
// Text
|
||||||
|
color: 'var(--mui-palette-text-primary)'
|
||||||
|
color: 'var(--mui-palette-text-secondary, #666)'
|
||||||
|
|
||||||
|
// Backgrounds
|
||||||
|
backgroundColor: 'var(--mui-palette-background-default, #fafafa)'
|
||||||
|
backgroundColor: 'var(--mui-palette-background-paper, #fff)'
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
border: '1px solid var(--mui-palette-divider, #e0e0e0)'
|
||||||
|
|
||||||
|
// Interactive
|
||||||
|
backgroundColor: 'var(--mui-palette-primary-main, #1976d2)'
|
||||||
|
color: 'var(--mui-palette-primary-contrastText, #fff)'
|
||||||
|
|
||||||
|
// Disabled states
|
||||||
|
backgroundColor: 'var(--mui-palette-action-disabledBackground, #e0e0e0)'
|
||||||
|
color: 'var(--mui-palette-action-disabled, #9e9e9e)'
|
||||||
|
|
||||||
|
// Links
|
||||||
|
color: 'var(--link-color, #1976d2)'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common mistakes to avoid
|
||||||
|
- **NEVER** use raw `#fff`, `#000`, `#333`, `#666` etc. without wrapping in `var(--mui-palette-*)`
|
||||||
|
- **NEVER** use `rgba(0,0,0,0.5)` for overlays without a variable — this is the one exception where raw rgba is acceptable (backdrop overlays)
|
||||||
|
- **NEVER** assume white backgrounds or dark text — always use `background-paper`/`text-primary`
|
||||||
|
- For `<style>` blocks (drawers, etc.), use the same CSS variables in the stylesheet
|
||||||
|
- Fallback values after the comma are for environments where the variable isn't set — always use the light-mode default
|
||||||
|
|
||||||
|
### Form inputs in custom components
|
||||||
|
```typescript
|
||||||
|
const inputStyle = {
|
||||||
|
border: '1px solid var(--mui-palette-divider, #ccc)',
|
||||||
|
borderRadius: '4px',
|
||||||
|
backgroundColor: 'var(--mui-palette-background-paper)',
|
||||||
|
color: 'var(--mui-palette-text-primary)',
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Quality Rules
|
||||||
|
|
||||||
|
1. **Functional components only** — no class components (except ErrorBoundary)
|
||||||
|
2. **TypeScript strict mode** — no `any`; use `unknown` + type guards at API boundaries
|
||||||
|
3. **Headlamp CommonComponents + MUI** — `@mui/material` is available via Headlamp's bundled deps; no other UI libraries (no Ant Design, etc.)
|
||||||
|
4. **Inline CSS only** — `style={{}}` props, CSS variables (`var(--mui-palette-*)`) for theming
|
||||||
|
5. **Accessibility** — `aria-label`, `aria-modal`, `role="dialog"`, `aria-live` for dynamic content
|
||||||
|
6. **Cancellation safety** — async effects must check a `cancelled` flag
|
||||||
|
7. **Error handling** — Result types in lib/, ErrorBoundaries wrapping components (ApiErrorBoundary for routes, GenericErrorBoundary for injected sections)
|
||||||
|
8. **Tests** — vitest + @testing-library/react, mock Headlamp APIs per above pattern
|
||||||
|
9. Run `npm run tsc` and `npm test` after implementation changes
|
||||||
@@ -47,7 +47,7 @@ jobs:
|
|||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
- name: Update version in package.json
|
- name: Update version in package.json
|
||||||
run: npm version ${{ inputs.version }} --no-git-tag-version
|
run: npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version
|
||||||
|
|
||||||
- name: Update artifacthub-pkg.yml
|
- name: Update artifacthub-pkg.yml
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
+18
-1
@@ -6,6 +6,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.2.21] - 2026-03-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Claude Code agent definitions for Headlamp plugin development assistance
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Hardcoded color in SealingKeysView now uses CSS variable for dark mode support
|
||||||
|
- Missing async cancellation in SealedSecretDetail useEffect
|
||||||
|
- Accessibility gaps: added aria-labels to detail panel buttons and dialogs
|
||||||
|
- Replaced `any` types with proper typed row interfaces in SimpleTable getters
|
||||||
|
- Corrected broken links, stale versions, and dead references across documentation
|
||||||
|
- Fixed LICENSE and README links in README.md
|
||||||
|
- Fixed appVersion mismatch in artifacthub-pkg.yml
|
||||||
|
- Removed dead documentation links from docs/README.md
|
||||||
|
|
||||||
## [0.2.4] - 2026-02-12
|
## [0.2.4] - 2026-02-12
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
@@ -110,7 +126,8 @@ Version 0.2.3 was published but with checksum mismatch on Artifact Hub. Supersed
|
|||||||
- Dependencies: node-forge for cryptography
|
- Dependencies: node-forge for cryptography
|
||||||
- Compatible with Headlamp v0.13.0+
|
- Compatible with Headlamp v0.13.0+
|
||||||
|
|
||||||
[Unreleased]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/compare/v0.2.4...HEAD
|
[Unreleased]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/compare/v0.2.21...HEAD
|
||||||
|
[0.2.21]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/compare/v0.2.20...v0.2.21
|
||||||
[0.1.0]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/tag/v0.1.0
|
[0.1.0]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/tag/v0.1.0
|
||||||
[0.2.4]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/tag/v0.2.4
|
[0.2.4]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/tag/v0.2.4
|
||||||
[0.2.3]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/tag/v0.2.3
|
[0.2.3]: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/tag/v0.2.3
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Uses custom hooks (`hooks/`) and a utility library (`lib/`) instead of a single
|
|||||||
|
|
||||||
- Functional React components only — no class components
|
- Functional React components only — no class components
|
||||||
- All imports from `@kinvolk/headlamp-plugin/lib` and `@kinvolk/headlamp-plugin/lib/CommonComponents`
|
- All imports from `@kinvolk/headlamp-plugin/lib` and `@kinvolk/headlamp-plugin/lib/CommonComponents`
|
||||||
- No additional UI libraries (no MUI direct imports, no Ant Design, etc.)
|
- MUI (`@mui/material`) is available via Headlamp's bundled dependencies — no other UI libraries (no Ant Design, etc.)
|
||||||
- TypeScript strict mode — no `any`, use `unknown` + type guards at API boundaries
|
- TypeScript strict mode — no `any`, use `unknown` + type guards at API boundaries
|
||||||
- Tests: vitest + @testing-library/react, mock with `vi.mock('@kinvolk/headlamp-plugin/lib', ...)`
|
- Tests: vitest + @testing-library/react, mock with `vi.mock('@kinvolk/headlamp-plugin/lib', ...)`
|
||||||
- `vitest.setup.ts` provides a spec-compliant `localStorage` shim for Node 22+ compatibility
|
- `vitest.setup.ts` provides a spec-compliant `localStorage` shim for Node 22+ compatibility
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
[](https://opensource.org/licenses/Apache-2.0)
|
[](https://opensource.org/licenses/Apache-2.0)
|
||||||
[](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases)
|
[](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases)
|
||||||
[](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/issues)
|
[](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/issues)
|
||||||
[](headlamp-sealed-secrets/)
|
[](docs/development/testing.md)
|
||||||
[](https://www.typescriptlang.org/)
|
[](https://www.typescriptlang.org/)
|
||||||
|
|
||||||
A comprehensive [Headlamp](https://headlamp.dev) plugin for managing [Bitnami Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) with **client-side encryption** and **RBAC-aware UI**.
|
A comprehensive [Headlamp](https://headlamp.dev) plugin for managing [Bitnami Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) with **client-side encryption** and **RBAC-aware UI**.
|
||||||
@@ -31,21 +31,23 @@ Browse the Headlamp Plugin Manager (Settings → Plugins → Catalog) and instal
|
|||||||
|
|
||||||
#### Option 2: Manual Tarball Install
|
#### Option 2: Manual Tarball Install
|
||||||
|
|
||||||
```bash
|
Download the latest tarball from the [Releases page](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases), then extract it into your Headlamp plugins directory:
|
||||||
# 1. Download and extract plugin
|
|
||||||
curl -LO https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/download/v0.2.4/headlamp-sealed-secrets-0.2.4.tar.gz
|
|
||||||
tar -xzf headlamp-sealed-secrets-0.2.4.tar.gz -C ~/Library/Application\ Support/Headlamp/plugins/
|
|
||||||
|
|
||||||
# 2. Restart Headlamp
|
```bash
|
||||||
# macOS: Cmd+Q then reopen
|
# macOS
|
||||||
# Linux: killall headlamp && headlamp
|
tar -xzf sealed-secrets-*.tar.gz -C ~/Library/Application\ Support/Headlamp/plugins/
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
tar -xzf sealed-secrets-*.tar.gz -C ~/.config/Headlamp/plugins/
|
||||||
|
|
||||||
|
# Restart Headlamp after installing
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Option 3: Build from Source
|
#### Option 3: Build from Source
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin.git
|
git clone https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin.git
|
||||||
cd headlamp-sealed-secrets-plugin/headlamp-sealed-secrets
|
cd headlamp-sealed-secrets-plugin
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
npx @kinvolk/headlamp-plugin extract . /headlamp/plugins
|
npx @kinvolk/headlamp-plugin extract . /headlamp/plugins
|
||||||
@@ -76,15 +78,11 @@ kubectl get secret <your-secret-name> -n <namespace>
|
|||||||
- **[Quick Start Tutorial](docs/getting-started/quick-start.md)** - Create your first sealed secret
|
- **[Quick Start Tutorial](docs/getting-started/quick-start.md)** - Create your first sealed secret
|
||||||
|
|
||||||
### User Guides
|
### User Guides
|
||||||
- **[Creating Secrets](docs/user-guide/creating-secrets.md)** - Encrypt and create sealed secrets
|
|
||||||
- **[Managing Keys](docs/user-guide/managing-keys.md)** - View and download sealing certificates
|
|
||||||
- **[Scopes Explained](docs/user-guide/scopes-explained.md)** - Strict vs namespace-wide vs cluster-wide
|
- **[Scopes Explained](docs/user-guide/scopes-explained.md)** - Strict vs namespace-wide vs cluster-wide
|
||||||
- **[RBAC Permissions](docs/user-guide/rbac-permissions.md)** - Configure access control
|
- **[RBAC Permissions](docs/user-guide/rbac-permissions.md)** - Configure access control
|
||||||
|
|
||||||
### Tutorials
|
### Tutorials
|
||||||
- **[CI/CD Integration](docs/tutorials/ci-cd-integration.md)** - GitHub Actions, GitLab CI, Jenkins
|
- **[CI/CD Integration](docs/tutorials/ci-cd-integration.md)** - GitHub Actions, GitLab CI, Jenkins
|
||||||
- **[Multi-Cluster Setup](docs/tutorials/multi-cluster-setup.md)** - Manage secrets across clusters
|
|
||||||
- **[Secret Rotation](docs/tutorials/secret-rotation.md)** - Rotate secrets and sealing keys safely
|
|
||||||
|
|
||||||
### Reference
|
### Reference
|
||||||
- **[Troubleshooting](docs/troubleshooting/)** - Common issues and solutions
|
- **[Troubleshooting](docs/troubleshooting/)** - Common issues and solutions
|
||||||
@@ -181,7 +179,7 @@ Plaintext values never leave your browser.
|
|||||||
| Browser XSS | Headlamp CSP policies | ⚠️ Standard web security |
|
| Browser XSS | Headlamp CSP policies | ⚠️ Standard web security |
|
||||||
| Supply chain | Package locks, dependabot | ⚠️ Ongoing monitoring |
|
| Supply chain | Package locks, dependabot | ⚠️ Ongoing monitoring |
|
||||||
|
|
||||||
See: [Security Hardening Guide](docs/deployment/security-hardening.md) | [ADR 003: Client-Side Encryption](docs/architecture/adr/003-client-side-crypto.md)
|
See: [ADR 003: Client-Side Encryption](docs/architecture/adr/003-client-side-crypto.md)
|
||||||
|
|
||||||
## Technical Details
|
## Technical Details
|
||||||
|
|
||||||
@@ -189,11 +187,8 @@ See: [Security Hardening Guide](docs/deployment/security-hardening.md) | [ADR 00
|
|||||||
|
|
||||||
| Metric | Value | Notes |
|
| Metric | Value | Notes |
|
||||||
|--------|-------|-------|
|
|--------|-------|-------|
|
||||||
| **Bundle Size** | 359.73 kB (98.79 kB gzipped) | Optimized with tree-shaking |
|
| **Test Coverage** | 92% | Unit + integration tests |
|
||||||
| **Test Coverage** | 92% (36/39 passing) | Unit + integration tests |
|
|
||||||
| **TypeScript** | 5.6.2 strict mode | Zero type errors |
|
| **TypeScript** | 5.6.2 strict mode | Zero type errors |
|
||||||
| **Lines of Code** | 4,767 TypeScript/React | Well-documented with JSDoc |
|
|
||||||
| **Build Time** | ~4 seconds | Fast development iteration |
|
|
||||||
| **Dependencies** | node-forge (crypto) | Minimal, audited dependencies |
|
| **Dependencies** | node-forge (crypto) | Minimal, audited dependencies |
|
||||||
|
|
||||||
### Technology Stack
|
### Technology Stack
|
||||||
@@ -223,7 +218,7 @@ We welcome contributions.
|
|||||||
```bash
|
```bash
|
||||||
# 1. Fork and clone
|
# 1. Fork and clone
|
||||||
git clone https://github.com/YOUR_USERNAME/headlamp-sealed-secrets-plugin
|
git clone https://github.com/YOUR_USERNAME/headlamp-sealed-secrets-plugin
|
||||||
cd headlamp-sealed-secrets-plugin/headlamp-sealed-secrets
|
cd headlamp-sealed-secrets-plugin
|
||||||
|
|
||||||
# 2. Install dependencies
|
# 2. Install dependencies
|
||||||
npm install
|
npm install
|
||||||
@@ -265,7 +260,7 @@ See: [Development Workflow](docs/development/workflow.md) | [Testing Guide](docs
|
|||||||
|
|
||||||
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
See [CHANGELOG.md](CHANGELOG.md) for version history.
|
||||||
|
|
||||||
**Latest release (v0.2.4)**: Type-safe error handling, RBAC integration, accessibility improvements, and 92% test coverage.
|
See [CHANGELOG.md](CHANGELOG.md) for details on each release.
|
||||||
|
|
||||||
## Issues & Support
|
## Issues & Support
|
||||||
|
|
||||||
@@ -292,13 +287,13 @@ See [CHANGELOG.md](CHANGELOG.md) for version history.
|
|||||||
| Issue | Quick Fix | Guide |
|
| Issue | Quick Fix | Guide |
|
||||||
|-------|-----------|-------|
|
|-------|-----------|-------|
|
||||||
| Plugin not loading | Check installation path | [Installation](docs/getting-started/installation.md) |
|
| Plugin not loading | Check installation path | [Installation](docs/getting-started/installation.md) |
|
||||||
| Controller not found | Install controller | [Controller Issues](docs/troubleshooting/controller-issues.md) |
|
| Controller not found | Install controller | [Troubleshooting](docs/troubleshooting/) |
|
||||||
| Permission denied | Configure RBAC | [Permission Errors](docs/troubleshooting/permission-errors.md) |
|
| Permission denied | Configure RBAC | [RBAC Permissions](docs/user-guide/rbac-permissions.md) |
|
||||||
| Encryption fails | Check certificate | [Encryption Failures](docs/troubleshooting/encryption-failures.md) |
|
| Encryption fails | Check certificate | [Troubleshooting](docs/troubleshooting/) |
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Apache License 2.0 - see [LICENSE](headlamp-sealed-secrets/LICENSE) for details.
|
Apache License 2.0 - see [LICENSE](LICENSE) for details.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
|||||||
+5
-6
@@ -1,13 +1,13 @@
|
|||||||
# Artifact Hub package metadata file
|
# Artifact Hub package metadata file
|
||||||
# https://github.com/artifacthub/hub/blob/master/docs/metadata/artifacthub-pkg.yml
|
# https://github.com/artifacthub/hub/blob/master/docs/metadata/artifacthub-pkg.yml
|
||||||
version: "0.2.19"
|
version: "0.2.21"
|
||||||
name: sealed-secrets
|
name: sealed-secrets
|
||||||
displayName: Sealed Secrets
|
displayName: Sealed Secrets
|
||||||
createdAt: "2026-02-12T00:00:00Z"
|
createdAt: "2026-02-12T00:00:00Z"
|
||||||
description: A comprehensive Headlamp plugin for managing Bitnami Sealed Secrets with client-side encryption and RBAC-aware UI
|
description: A comprehensive Headlamp plugin for managing Bitnami Sealed Secrets with client-side encryption and RBAC-aware UI
|
||||||
license: Apache-2.0
|
license: Apache-2.0
|
||||||
homeURL: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin
|
homeURL: https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin
|
||||||
appVersion: 0.2.18
|
appVersion: 0.2.21
|
||||||
containersImages:
|
containersImages:
|
||||||
- name: sealed-secrets-controller
|
- name: sealed-secrets-controller
|
||||||
image: docker.io/bitnami/sealed-secrets-controller:v0.24.0
|
image: docker.io/bitnami/sealed-secrets-controller:v0.24.0
|
||||||
@@ -19,8 +19,7 @@ keywords:
|
|||||||
- encryption
|
- encryption
|
||||||
- security
|
- security
|
||||||
annotations:
|
annotations:
|
||||||
headlamp/plugin/archive-url: "https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/download/v0.2.19/sealed-secrets-0.2.19.tar.gz"
|
headlamp/plugin/archive-url: "https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/releases/download/v0.2.21/sealed-secrets-0.2.21.tar.gz"
|
||||||
headlamp/plugin/archive-checksum: sha256:75a72b0162ed6b38215f1c1a3cca2f8a076947b503e1b5d59c55b6fe3079ee8d
|
|
||||||
headlamp/plugin/version-compat: ">=0.13.0"
|
headlamp/plugin/version-compat: ">=0.13.0"
|
||||||
headlamp/plugin/distro-compat: "desktop,in-cluster,web,docker-desktop"
|
headlamp/plugin/distro-compat: "desktop,in-cluster,web,docker-desktop"
|
||||||
links:
|
links:
|
||||||
@@ -51,7 +50,7 @@ install: |
|
|||||||
#### Option 2: Build from Source
|
#### Option 2: Build from Source
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin
|
git clone https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin
|
||||||
cd headlamp-sealed-secrets-plugin/headlamp-sealed-secrets
|
cd headlamp-sealed-secrets-plugin
|
||||||
npm install
|
npm install
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
@@ -69,7 +68,7 @@ install: |
|
|||||||
- Manage sealing keys
|
- Manage sealing keys
|
||||||
- Configure controller settings
|
- Configure controller settings
|
||||||
|
|
||||||
For detailed usage instructions, see the [README](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/blob/main/headlamp-sealed-secrets/README.md).
|
For detailed usage instructions, see the [README](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/blob/main/README.md).
|
||||||
maintainers:
|
maintainers:
|
||||||
- name: privilegedescalation
|
- name: privilegedescalation
|
||||||
email: privilegedescalation@users.noreply.github.com
|
email: privilegedescalation@users.noreply.github.com
|
||||||
|
|||||||
+4
-117
@@ -2,158 +2,45 @@
|
|||||||
|
|
||||||
Complete documentation for the Headlamp Sealed Secrets plugin.
|
Complete documentation for the Headlamp Sealed Secrets plugin.
|
||||||
|
|
||||||
## 📚 Documentation Index
|
## Documentation Index
|
||||||
|
|
||||||
### Getting Started
|
### Getting Started
|
||||||
|
|
||||||
New to the plugin? Start here:
|
|
||||||
|
|
||||||
- **[Installation Guide](getting-started/installation.md)** - Install the plugin on Headlamp
|
- **[Installation Guide](getting-started/installation.md)** - Install the plugin on Headlamp
|
||||||
- **[Quick Start](getting-started/quick-start.md)** - Create your first sealed secret in 5 minutes
|
- **[Quick Start](getting-started/quick-start.md)** - Create your first sealed secret in 5 minutes
|
||||||
|
|
||||||
### User Guide
|
### User Guide
|
||||||
|
|
||||||
Learn how to use all the features:
|
|
||||||
|
|
||||||
- **[Creating Secrets](user-guide/creating-secrets.md)** - Encrypt and create sealed secrets
|
|
||||||
- **[Managing Keys](user-guide/managing-keys.md)** - View and download sealing certificates
|
|
||||||
- **[Scopes Explained](user-guide/scopes-explained.md)** - Understand strict/namespace/cluster-wide scopes
|
- **[Scopes Explained](user-guide/scopes-explained.md)** - Understand strict/namespace/cluster-wide scopes
|
||||||
- **[RBAC Permissions](user-guide/rbac-permissions.md)** - Required permissions and access control
|
- **[RBAC Permissions](user-guide/rbac-permissions.md)** - Required permissions and access control
|
||||||
- **[Settings](user-guide/settings.md)** - Configure plugin behavior
|
|
||||||
|
|
||||||
### Tutorials
|
### Tutorials
|
||||||
|
|
||||||
Step-by-step guides for common workflows:
|
|
||||||
|
|
||||||
- **[CI/CD Integration](tutorials/ci-cd-integration.md)** - Automate secret creation with GitHub Actions, GitLab CI
|
- **[CI/CD Integration](tutorials/ci-cd-integration.md)** - Automate secret creation with GitHub Actions, GitLab CI
|
||||||
- **[Multi-Cluster Setup](tutorials/multi-cluster-setup.md)** - Manage secrets across multiple clusters
|
|
||||||
- **[Secret Rotation](tutorials/secret-rotation.md)** - Rotate secrets and sealing keys safely
|
|
||||||
- **[Disaster Recovery](tutorials/disaster-recovery.md)** - Backup and restore procedures
|
|
||||||
- **[Migration from kubeseal](tutorials/migration-from-kubeseal.md)** - Migrate from CLI-based workflow
|
|
||||||
|
|
||||||
### Troubleshooting
|
### Troubleshooting
|
||||||
|
|
||||||
Solutions for common issues:
|
|
||||||
|
|
||||||
- **[Common Errors](troubleshooting/common-errors.md)** - Error messages and fixes
|
- **[Common Errors](troubleshooting/common-errors.md)** - Error messages and fixes
|
||||||
- **[Controller Issues](troubleshooting/controller-issues.md)** - Connection and deployment problems
|
- **[Controller Issues](troubleshooting/controller-issues.md)** - Connection and deployment problems
|
||||||
- **[Encryption Failures](troubleshooting/encryption-failures.md)** - Debugging encryption errors
|
- **[Encryption Failures](troubleshooting/encryption-failures.md)** - Debugging encryption errors
|
||||||
- **[Permission Errors](troubleshooting/permission-errors.md)** - RBAC troubleshooting
|
- **[Permission Errors](troubleshooting/permission-errors.md)** - RBAC troubleshooting
|
||||||
- **[Performance](troubleshooting/performance.md)** - Optimization tips
|
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
|
|
||||||
Contributing to the plugin:
|
|
||||||
|
|
||||||
- **[Setup](development/setup.md)** - Development environment configuration
|
|
||||||
- **[Workflow](development/workflow.md)** - Development and testing workflow
|
- **[Workflow](development/workflow.md)** - Development and testing workflow
|
||||||
- **[Testing](development/testing.md)** - Running and writing tests
|
- **[Testing](development/testing.md)** - Running and writing tests
|
||||||
- **[Code Style](development/code-style.md)** - Coding standards
|
|
||||||
- **[Debugging](development/debugging.md)** - Debugging tips and tools
|
|
||||||
- **[Release Process](development/release-process.md)** - How to release new versions
|
|
||||||
|
|
||||||
### API Reference
|
|
||||||
|
|
||||||
Technical documentation:
|
|
||||||
|
|
||||||
- **[Functions](api-reference/functions.md)** - Exported function reference
|
|
||||||
- **[Types](api-reference/types.md)** - TypeScript type definitions
|
|
||||||
- **[Hooks](api-reference/hooks.md)** - React hooks API
|
|
||||||
- **[Components](api-reference/components.md)** - Component props reference
|
|
||||||
- **[Examples](api-reference/examples.md)** - Code examples and patterns
|
|
||||||
|
|
||||||
### Architecture
|
### Architecture
|
||||||
|
|
||||||
Technical design and decisions:
|
|
||||||
|
|
||||||
- **[Overview](architecture/overview.md)** - System architecture
|
|
||||||
- **[Encryption Flow](architecture/encryption-flow.md)** - How encryption works
|
|
||||||
- **[Type System](architecture/type-system.md)** - Result types and branded types explained
|
|
||||||
- **[Error Handling](architecture/error-handling.md)** - Error handling patterns
|
|
||||||
- **[Accessibility](architecture/accessibility.md)** - WCAG 2.1 AA compliance details
|
|
||||||
- **[ADRs](architecture/adr/)** - Architecture Decision Records
|
- **[ADRs](architecture/adr/)** - Architecture Decision Records
|
||||||
|
|
||||||
### Deployment
|
### API Reference
|
||||||
|
|
||||||
Production deployment guides:
|
- **[Generated API Docs](api-reference/generated/)** - Auto-generated TypeScript reference
|
||||||
|
|
||||||
- **[Kubernetes](deployment/kubernetes.md)** - Deploy in K8s clusters
|
## External Resources
|
||||||
- **[Helm](deployment/helm.md)** - Using with Helm deployments
|
|
||||||
- **[Security Hardening](deployment/security-hardening.md)** - Security best practices
|
|
||||||
- **[Monitoring](deployment/monitoring.md)** - Observability setup
|
|
||||||
|
|
||||||
## 🔍 Quick Links
|
|
||||||
|
|
||||||
### Popular Pages
|
|
||||||
|
|
||||||
- [Quick Start Guide](getting-started/quick-start.md) - Get started in 5 minutes
|
|
||||||
- [CI/CD Integration](tutorials/ci-cd-integration.md) - Automate your workflow
|
|
||||||
- [Troubleshooting](troubleshooting/README.md) - Solve common issues
|
|
||||||
- [Development Workflow](development/workflow.md) - Contribute to the plugin
|
|
||||||
|
|
||||||
### External Resources
|
|
||||||
|
|
||||||
- **GitHub**: [privilegedescalation/headlamp-sealed-secrets-plugin](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin)
|
- **GitHub**: [privilegedescalation/headlamp-sealed-secrets-plugin](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin)
|
||||||
- **Issues**: [Report bugs](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/issues)
|
- **Issues**: [Report bugs](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/issues)
|
||||||
- **Discussions**: [Ask questions](https://github.com/privilegedescalation/headlamp-sealed-secrets-plugin/discussions)
|
|
||||||
- **Headlamp**: [headlamp.dev](https://headlamp.dev)
|
- **Headlamp**: [headlamp.dev](https://headlamp.dev)
|
||||||
- **Sealed Secrets**: [bitnami-labs/sealed-secrets](https://github.com/bitnami-labs/sealed-secrets)
|
- **Sealed Secrets**: [bitnami-labs/sealed-secrets](https://github.com/bitnami-labs/sealed-secrets)
|
||||||
|
|
||||||
## 📖 About This Documentation
|
|
||||||
|
|
||||||
This documentation is organized by user journey:
|
|
||||||
|
|
||||||
- **Getting Started** - For new users
|
|
||||||
- **User Guide** - For daily usage
|
|
||||||
- **Tutorials** - For specific workflows
|
|
||||||
- **Troubleshooting** - For problem-solving
|
|
||||||
- **Development** - For contributors
|
|
||||||
- **API Reference** - For developers using the plugin
|
|
||||||
- **Architecture** - For understanding the design
|
|
||||||
- **Deployment** - For production deployments
|
|
||||||
|
|
||||||
## 🤝 Contributing to Docs
|
|
||||||
|
|
||||||
Found an error or want to improve the documentation?
|
|
||||||
|
|
||||||
1. **Quick fixes**: Edit on GitHub and submit a PR
|
|
||||||
2. **Larger changes**: Open an issue first to discuss
|
|
||||||
3. **New tutorials**: Share your use case in Discussions
|
|
||||||
|
|
||||||
See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines.
|
|
||||||
|
|
||||||
## 📝 Documentation Status
|
|
||||||
|
|
||||||
### Completed ✅
|
|
||||||
|
|
||||||
- Installation guides
|
|
||||||
- Quick start tutorial
|
|
||||||
- Development workflow documentation
|
|
||||||
- Testing guides
|
|
||||||
- Architecture overview
|
|
||||||
|
|
||||||
### In Progress 🚧
|
|
||||||
|
|
||||||
- User guide sections (creating secrets, managing keys, scopes)
|
|
||||||
- Tutorial content (CI/CD, multi-cluster, rotation)
|
|
||||||
- Troubleshooting guides
|
|
||||||
- API reference (auto-generated coming soon)
|
|
||||||
|
|
||||||
### Planned 📅
|
|
||||||
|
|
||||||
- Video tutorials
|
|
||||||
- Interactive examples
|
|
||||||
- Detailed architecture diagrams
|
|
||||||
- More CI/CD platform examples
|
|
||||||
- Advanced use cases
|
|
||||||
|
|
||||||
## 🔄 Documentation Updates
|
|
||||||
|
|
||||||
This documentation is kept in sync with code changes:
|
|
||||||
|
|
||||||
- **Version**: Matches plugin version (currently v0.2.0)
|
|
||||||
- **Auto-generated**: API reference generated from TypeScript source
|
|
||||||
- **CI Checks**: Links validated on every pull request
|
|
||||||
- **Examples Tested**: Code examples validated against current API
|
|
||||||
|
|
||||||
Last updated: 2026-02-12
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sealed-secrets",
|
"name": "sealed-secrets",
|
||||||
"version": "0.2.19",
|
"version": "0.2.21",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sealed-secrets",
|
"name": "sealed-secrets",
|
||||||
"version": "0.2.19",
|
"version": "0.2.21",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-forge": "^1.3.1"
|
"node-forge": "^1.3.1"
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sealed-secrets",
|
"name": "sealed-secrets",
|
||||||
"version": "0.2.19",
|
"version": "0.2.21",
|
||||||
"description": "Headlamp plugin for Bitnami Sealed Secrets - manage encrypted Kubernetes secrets",
|
"description": "Headlamp plugin for Bitnami Sealed Secrets - manage encrypted Kubernetes secrets",
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
|||||||
@@ -69,9 +69,15 @@ export function SealedSecretDetail() {
|
|||||||
|
|
||||||
// Check if user can decrypt secrets (requires get permission on Secrets)
|
// Check if user can decrypt secrets (requires get permission on Secrets)
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
|
let cancelled = false;
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
canDecryptSecrets(namespace).then(setCanDecrypt);
|
canDecryptSecrets(namespace).then((result) => {
|
||||||
|
if (!cancelled) setCanDecrypt(result);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
};
|
||||||
}, [namespace]);
|
}, [namespace]);
|
||||||
|
|
||||||
// Wait for required params before rendering
|
// Wait for required params before rendering
|
||||||
@@ -154,7 +160,7 @@ export function SealedSecretDetail() {
|
|||||||
title={
|
title={
|
||||||
<Box display="flex" alignItems="center" justifyContent="space-between">
|
<Box display="flex" alignItems="center" justifyContent="space-between">
|
||||||
<Box display="flex" alignItems="center" gap={1}>
|
<Box display="flex" alignItems="center" gap={1}>
|
||||||
<IconButton onClick={handleClose} edge="start" size="small">
|
<IconButton onClick={handleClose} edge="start" size="small" aria-label="Close detail panel">
|
||||||
<Icon icon="mdi:close" />
|
<Icon icon="mdi:close" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<span>{sealedSecret.metadata.name}</span>
|
<span>{sealedSecret.metadata.name}</span>
|
||||||
@@ -233,24 +239,24 @@ export function SealedSecretDetail() {
|
|||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
label: 'Key',
|
label: 'Key',
|
||||||
getter: (row: any) => row.key,
|
getter: (row: { key: string; value: string }) => row.key,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Encrypted Value',
|
label: 'Encrypted Value',
|
||||||
getter: (row: any) => {
|
getter: (row: { key: string; value: string }) => {
|
||||||
const val = row.value;
|
const val = row.value;
|
||||||
return val.length > 40 ? val.substring(0, 40) + '...' : val;
|
return val.length > 40 ? val.substring(0, 40) + '...' : val;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Actions',
|
label: 'Actions',
|
||||||
getter: (row: any) =>
|
getter: (row: { key: string; value: string }) =>
|
||||||
canDecrypt ? (
|
canDecrypt ? (
|
||||||
<Button size="small" onClick={() => setDecryptKey(row.key)}>
|
<Button size="small" onClick={() => setDecryptKey(row.key)} aria-label={`Decrypt ${row.key}`}>
|
||||||
Decrypt
|
Decrypt
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button size="small" disabled title="No permission to access Secrets">
|
<Button size="small" disabled title="No permission to access Secrets" aria-label={`Decrypt ${row.key} (no permission)`}>
|
||||||
Decrypt
|
Decrypt
|
||||||
</Button>
|
</Button>
|
||||||
),
|
),
|
||||||
@@ -331,8 +337,8 @@ export function SealedSecretDetail() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Dialog open={deleteDialogOpen} onClose={() => setDeleteDialogOpen(false)}>
|
<Dialog open={deleteDialogOpen} onClose={() => setDeleteDialogOpen(false)} aria-labelledby="delete-dialog-title">
|
||||||
<DialogTitle>Delete SealedSecret?</DialogTitle>
|
<DialogTitle id="delete-dialog-title">Delete SealedSecret?</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
Are you sure you want to delete the SealedSecret <strong>{name}</strong>? This will also
|
Are you sure you want to delete the SealedSecret <strong>{name}</strong>? This will also
|
||||||
delete the resulting Kubernetes Secret.
|
delete the resulting Kubernetes Secret.
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ export function SealingKeysView() {
|
|||||||
return (
|
return (
|
||||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||||
<span>{expiryDate}</span>
|
<span>{expiryDate}</span>
|
||||||
<span style={{ color: '#666', fontSize: '0.9em' }}>
|
<span style={{ color: 'var(--mui-palette-text-secondary, #666)', fontSize: '0.9em' }}>
|
||||||
({certInfo.daysUntilExpiry} days)
|
({certInfo.daysUntilExpiry} days)
|
||||||
</span>
|
</span>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user