fix(opnsense): switch secrets to api-key key and secret for easier understanding (#3744)

This commit is contained in:
Meier Lukas
2025-08-08 17:53:03 +02:00
committed by GitHub
parent 4a07b3f866
commit 7f474683a5
6 changed files with 70 additions and 4 deletions

View File

@@ -19,4 +19,6 @@ export const integrationSecretIcons = {
tokenId: IconGrid3x3,
personalAccessToken: IconPasswordUser,
topic: IconMessage,
opnsenseApiKey: IconKey,
opnsenseApiSecret: IconPassword,
} satisfies Record<IntegrationSecretKind, TablerIcon>;

View File

@@ -0,0 +1,52 @@
import type { Database } from "../..";
import { and, eq } from "../..";
import { integrationSecrets } from "../../schema";
/**
* Previously the credentials for OPNsense were stored as username and password.
* However it should have been the api key and secret.
* For more information see:
* https://docs.opnsense.org/development/how-tos/api.html#creating-keys
*/
export async function migrateOpnsenseCredentialsAsync(db: Database) {
const existingIntegrations = await db.query.integrations.findMany({
where: (table, { eq }) => eq(table.kind, "opnsense"),
with: {
secrets: true,
},
});
await Promise.all(
existingIntegrations.map(async (integration) => {
const username = integration.secrets.find((secret) => secret.kind === "username");
if (!username) return;
await db
.update(integrationSecrets)
.set({
kind: "opnsenseApiKey",
})
.where(
and(eq(integrationSecrets.integrationId, username.integrationId), eq(integrationSecrets.kind, "username")),
);
}),
);
await Promise.all(
existingIntegrations.map(async (integration) => {
const password = integration.secrets.find((secret) => secret.kind === "password");
if (!password) return;
await db
.update(integrationSecrets)
.set({
kind: "opnsenseApiSecret",
})
.where(
and(eq(integrationSecrets.integrationId, password.integrationId), eq(integrationSecrets.kind, "password")),
);
}),
);
if (existingIntegrations.length > 0) {
console.log(`Migrated OPNsense credentials count="${existingIntegrations.length}"`);
}
}

View File

@@ -1,6 +1,8 @@
import type { Database } from "../..";
import { migrateReleaseWidgetProviderToOptionsAsync } from "./0000_release_widget_provider_to_options";
import { migrateOpnsenseCredentialsAsync } from "./0001_opnsense_credentials";
export const applyCustomMigrationsAsync = async (db: Database) => {
await migrateReleaseWidgetProviderToOptionsAsync(db);
await migrateOpnsenseCredentialsAsync(db);
};

View File

@@ -9,6 +9,8 @@ export const integrationSecretKindObject = {
realm: { isPublic: true },
personalAccessToken: { isPublic: false },
topic: { isPublic: true },
opnsenseApiKey: { isPublic: false },
opnsenseApiSecret: { isPublic: false },
} satisfies Record<string, { isPublic: boolean }>;
export const integrationSecretKinds = objectKeys(integrationSecretKindObject);
@@ -174,7 +176,7 @@ export const integrationDefs = {
},
opnsense: {
name: "OPNsense",
secretKinds: [["username", "password"]],
secretKinds: [["opnsenseApiKey", "opnsenseApiSecret"]],
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/opnsense.svg",
category: ["firewall"],
},

View File

@@ -37,9 +37,9 @@ export class OPNsenseIntegration extends Integration implements FirewallSummaryI
}
private getAuthHeaders() {
const username = super.getSecretValue("username");
const password = super.getSecretValue("password");
return `Basic ${btoa(`${username}:${password}`)}`;
const key = super.getSecretValue("opnsenseApiKey");
const secret = super.getSecretValue("opnsenseApiSecret");
return `Basic ${btoa(`${key}:${secret}`)}`;
}
public async getFirewallVersionAsync(): Promise<FirewallVersionSummary> {

View File

@@ -944,6 +944,14 @@
"topic": {
"label": "Topic",
"newLabel": "New topic"
},
"opnsenseApiKey": {
"label": "API Key (Key)",
"newLabel": "New API Key (Key)"
},
"opnsenseApiSecret": {
"label": "API Key (Secret)",
"newLabel": "New API Key (Secret)"
}
}
},