From 9ef516f404baf32198bcbf76427cc75e89192d23 Mon Sep 17 00:00:00 2001 From: haritz Date: Thu, 2 Jan 2025 18:57:45 +0100 Subject: [PATCH] adding new features and qol for dms options Signed-off-by: haritz --- env-docker-config.js | 2 +- src/ducks/features/dmss/models.ts | 24 +++- src/views/DMS/DMSCreateUpdate.tsx | 183 ++++++++++++++++++++++++++---- 3 files changed, 185 insertions(+), 24 deletions(-) diff --git a/env-docker-config.js b/env-docker-config.js index ce50f6d..01edf67 100644 --- a/env-docker-config.js +++ b/env-docker-config.js @@ -21,7 +21,7 @@ window._env_ = { LAMASSU_DMS_MANAGER_API: `https://${DOMAIN}/api/dmsmanager`, LAMASSU_DEVMANAGER_API:`https://${DOMAIN}/api/devmanager`, LAMASSU_ALERTS_API:`https://${DOMAIN}/api/alerts`, - LAMASSU_VA:`https://${DOMAIN}/api/va`, + LAMASSU_VA_API:`https://${DOMAIN}/api/va`, LAMASSU_VDMS:``, LAMASSU_VDEVICE:``, CLOUD_CONNECTORS: $CLOUD_CONNECTORS diff --git a/src/ducks/features/dmss/models.ts b/src/ducks/features/dmss/models.ts index 737c964..88b8890 100644 --- a/src/ducks/features/dmss/models.ts +++ b/src/ducks/features/dmss/models.ts @@ -32,6 +32,7 @@ export enum EnrollmentRegistrationMode { export enum ESTAuthMode { NoAuth = "NO_AUTH", ClientCertificate = "CLIENT_CERTIFICATE", + ExternalWebhook = "EXTERNAL_WEBHOOK", } export type AuthOptionsClientCertificate = { @@ -43,6 +44,26 @@ export type AuthOptionsClientCertificate = { export type EST7030Settings = { auth_mode: ESTAuthMode, client_certificate_settings: AuthOptionsClientCertificate, + external_webhook?: Webhook, +} + +export type Webhook = { + url: string, + name: string, + validate_server_cert: boolean, + config: { + log_level: string, + auth_mode: string, + oidc?: { + client_id: string, + client_secret: string, + well_known: string, + }, + apikey?: { + header: string, + key: string, + } + } } export type EnrollmentSettings = { @@ -63,13 +84,14 @@ export type ReEnrollmentSettings = { additional_validation_cas: string[], reenrollment_delta: string, enable_expired_renewal: boolean, + revoke_on_reenrollment: boolean, preventive_delta: string, critical_delta: string, } export type ServerKeygenSettings = { enabled: boolean, - key:{ + key: { type: "RSA" | "ECDSA", bits: number } diff --git a/src/views/DMS/DMSCreateUpdate.tsx b/src/views/DMS/DMSCreateUpdate.tsx index 5278a2d..d39418f 100644 --- a/src/views/DMS/DMSCreateUpdate.tsx +++ b/src/views/DMS/DMSCreateUpdate.tsx @@ -49,6 +49,24 @@ type FormData = { chainValidation: number; validationCAs: CertificateAuthority[]; allowExpired: boolean; + }, + external_webhook?: { + name: string; + url: string; + validateServeCert: boolean; + config: { + log_level: string; + auth_mode: "jwt" | "noauth" | "apikey" // mtls is also an option but requires handling persisting the client certificate in the fs as well as in the DB + oidc?: { + well_known: string; + client_id: string; + client_secret: string; + }, + apikey?: { + header: string; + key: string; + } + } } } enrollDeviceRegistration: { @@ -60,6 +78,7 @@ type FormData = { preventiveDelta: string; criticalDelta: string; allowExpired: boolean; + revokeOnReenroll: boolean; additionalValidationCAs: CertificateAuthority[]; }, serverKeyGen: { @@ -124,7 +143,25 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" }, registrationMode: EnrollmentRegistrationMode.JITP, overrideEnrollment: false, - enrollmentCA: undefined + enrollmentCA: undefined, + external_webhook: { + name: "", + url: "", + validateServeCert: true, + config: { + log_level: "info", + auth_mode: "noauth", + oidc: { + well_known: "", + client_id: "", + client_secret: "" + }, + apikey: { + header: "", + key: "" + } + } + } }, enrollDeviceRegistration: { icon: { @@ -135,6 +172,7 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" tags: ["iot"] }, reEnroll: { + revokeOnReenroll: true, allowedRenewalDelta: "100d", preventiveDelta: "31d", criticalDelta: "7d", @@ -171,6 +209,8 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" const watchEnrollmentCA = watch("enrollProtocol.enrollmentCA"); const watchAwsIotIntegration = watch("awsIotIntegration"); const watchServerKeyGen = watch("serverKeyGen"); + const watchEstAuthMode = watch("enrollProtocol.estAuthMode"); + const watchEnrollAuthWebhook = watch("enrollProtocol.external_webhook"); useEffect(() => { if (!editMode) { @@ -236,6 +276,7 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" }, reEnroll: { allowedRenewalDelta: dms!.settings.reenrollment_settings.reenrollment_delta, + revokeOnReenroll: dms!.settings.reenrollment_settings.revoke_on_reenrollment, allowExpired: dms!.settings.reenrollment_settings.enable_expired_renewal, additionalValidationCAs: dms!.settings.reenrollment_settings.additional_validation_cas.map(ca => casResp.list.find(caF => caF.id === ca)!), preventiveDelta: dms.settings.reenrollment_settings.preventive_delta, @@ -279,6 +320,21 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" }; } + if (dms.settings.enrollment_settings.est_rfc7030_settings.external_webhook !== undefined) { + const webhookConf = dms.settings.enrollment_settings.est_rfc7030_settings.external_webhook; + updateDMS.enrollProtocol.external_webhook = { + name: webhookConf.name, + url: webhookConf.url, + validateServeCert: webhookConf.validate_server_cert, + config: { + log_level: webhookConf.config.log_level, + auth_mode: webhookConf.config.auth_mode as "jwt" | "noauth" | "apikey", + oidc: webhookConf.config.oidc, + apikey: webhookConf.config.apikey + } + }; + } + const dmsMeta = dms.metadata; const firstConnectorKey = Object.keys(dmsMeta).find(key => key.includes("lamassu.io/iot/")); @@ -384,7 +440,24 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" chain_level_validation: Number(data.enrollProtocol.certificateValidation.chainValidation), validation_cas: data.enrollProtocol.certificateValidation.validationCAs.map(ca => ca.id), allow_expired: data.enrollProtocol.certificateValidation.allowExpired - } + }, + external_webhook: data.enrollProtocol.estAuthMode === ESTAuthMode.ExternalWebhook + ? { + name: data.enrollProtocol.external_webhook!.name, + url: data.enrollProtocol.external_webhook!.url, + validate_server_cert: data.enrollProtocol.external_webhook!.validateServeCert, + config: { + log_level: data.enrollProtocol.external_webhook!.config.log_level, + auth_mode: data.enrollProtocol.external_webhook!.config.auth_mode, + apikey: data.enrollProtocol.external_webhook!.config.auth_mode === "apikey" + ? data.enrollProtocol.external_webhook!.config.apikey + : undefined, + oidc: data.enrollProtocol.external_webhook!.config.auth_mode === "jwt" + ? data.enrollProtocol.external_webhook!.config.oidc + : undefined + } + } + : undefined }, device_provisioning_profile: { icon: data.enrollDeviceRegistration.icon.name, @@ -395,6 +468,7 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" registration_mode: data.enrollProtocol.registrationMode }, reenrollment_settings: { + revoke_on_reenrollment: data.reEnroll.revokeOnReenroll, enable_expired_renewal: data.reEnroll.allowExpired, critical_delta: data.reEnroll.criticalDelta, preventive_delta: data.reEnroll.preventiveDelta, @@ -476,15 +550,6 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" { value: EnrollmentProtocols.EST, render: "EST" } ]} /> - - - - - - { if (!Array.isArray(elems)) { @@ -494,21 +559,92 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" /> - { - if (Array.isArray(elems)) { - setValue("enrollProtocol.certificateValidation.validationCAs", elems); - } - }} multiple={true} label="Validation CAs" - /> - - - + - + + { + watchEstAuthMode === ESTAuthMode.ClientCertificate && ( + <> + + { + if (Array.isArray(elems)) { + setValue("enrollProtocol.certificateValidation.validationCAs", elems); + } + }} multiple={true} label="Validation CAs" + /> + + + + + + + + + ) + } + { + watchEstAuthMode === ESTAuthMode.ExternalWebhook && ( + <> + + + + + + + + + + + + + { + watchEnrollAuthWebhook!.config.auth_mode === "jwt" && ( + <> + + + + + + + + + + + ) + }, + { + watchEnrollAuthWebhook!.config.auth_mode === "apikey" && ( + <> + + + + + + + + + + ) + } + + ) + } - @@ -517,6 +653,9 @@ export const DMSForm: React.FC = ({ dms, onSubmit, actionLabel = "Create" ReEnrollment Settings + + +