From: Abhishek Desai Date: Mon, 15 Jun 2026 11:12:15 +0000 (+0530) Subject: mgr/dashboard : Enable cephadm-signed TLS for NVMeOf X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3407863f99553bca009c31119795e6fd8d25386c;p=ceph.git mgr/dashboard : Enable cephadm-signed TLS for NVMeOf fixes: https://tracker.ceph.com/issues/77406 Signed-off-by: Abhishek Desai --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts index 6be23e612fa..ab67956ff4e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/cluster.module.ts @@ -104,6 +104,7 @@ import { MultiClusterFormComponent } from './multi-cluster/multi-cluster-form/mu import { MultiClusterListComponent } from './multi-cluster/multi-cluster-list/multi-cluster-list.component'; import { DashboardV3Module } from '../dashboard-v3/dashboard-v3.module'; import { MultiClusterDetailsComponent } from './multi-cluster/multi-cluster-details/multi-cluster-details.component'; +import { CertificateAuthorityFormComponent } from '~/app/shared/components/certificate-authority-form/certificate-authority-form.component'; import { TextLabelListComponent } from '~/app/shared/components/text-label-list/text-label-list.component'; @NgModule({ @@ -143,6 +144,7 @@ import { TextLabelListComponent } from '~/app/shared/components/text-label-list/ TagModule, TabsModule, TextLabelListComponent, + CertificateAuthorityFormComponent, SelectModule, LayoutModule, NumberModule, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html index 1122ccb134d..58613e00cfc 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.html @@ -1666,7 +1666,14 @@ serviceForm.controls.service_type.value ) ) { - + + } @@ -1898,7 +1905,14 @@ @if (serviceForm.controls.enable_mtls.value) { - + + @if (serviceForm.controls.certificateType.value === CertificateType.external) { @@ -2064,174 +2078,6 @@ - -
- - @if (editing && currentCertificate?.has_certificate) { -
- - Current Certificate - -
-
- - Certificate - -
{{ currentCertificate.cert_name }}
-
-
- - Valid Until - -
- {{ currentCertificate.expiry_date | cdDate }} • - {{ currentCertificate.days_to_expiration }} days left -
-
-
-
-
- - Status - -
- - @switch (currentCertificate.status) { - @case ('valid') { - Valid - } - @case ('expiring') { - Expiring soon - } - @case ('expired') { - Expired - } - @case ('not_configured') { - Not configured - } - @case ('invalid') { - Invalid - } - @default { - {{ currentCertificate.status }} - } - } -
-
-
- - Issuer - -
- @if (currentCertificate.signed_by === 'cephadm') { - Internal (Cephadm CA) - } @else { - {{ currentCertificate.issuer || 'External' }} - } -
-
-
-
- } - - -
- - - - Internal - - - External - - -
- - @if (showCertSourceChangeWarning) { - - Changing the certificate source will redeploy the service daemons to apply the new - certificate configuration. - - } - - @if (serviceForm.controls.certificateType.value === CertificateType.internal) { - - Certificate will be generated automatically by Cephadm CA for internal certificate type. - -
- - -
- @if ( - serviceForm.controls.service_type.value === 'rgw' && - serviceForm.controls.virtual_host_enabled.value - ) { -
- - Include wildcard certificate for bucket subdomains - - Add wildcard certificates (*.domain) to allow SSL for all bucket subdomains. Required - for virtual-host style with SSL. - - -
- } - } -
-
- ; currentCertificate: CephServiceCertificate = null; currentSpecCertificateSource: string = null; - statusIconMap = CERTIFICATE_STATUS_ICON_MAP; constructor( public actionLabels: ActionLabelsI18n, diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.html new file mode 100644 index 00000000000..81578747d32 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.html @@ -0,0 +1,214 @@ +
+ @if (editing && currentCertificate?.has_certificate) { +
+ Current Certificate +
+
+
+ Certificate + {{ currentCertificate.cert_name }} +
+
+
+
+ Valid Until + + {{ currentCertificate.expiry_date | cdDate }} • + {{ currentCertificate.days_to_expiration }} + days left + +
+
+
+
+
+
+ Status +
+ + @switch (currentCertificate.status) { + @case ('valid') { + Valid + } + @case ('expiring') { + Expiring soon + } + @case ('expired') { + Expired + } + @case ('not_configured') { + Not configured + } + @case ('invalid') { + Invalid + } + @default { + {{ currentCertificate.status }} + } + } +
+
+
+
+
+ Issuer + + @if (currentCertificate.signed_by === 'cephadm') { + Internal (Cephadm CA) + } @else { + {{ currentCertificate.issuer || 'External' }} + } + +
+
+
+
+ } + +
+ + + + Internal + + + External + + +
+ + @if (showCertSourceChangeWarning) { + + Changing the certificate source will redeploy the service daemons to apply the new certificate + configuration. + + } + + @if (formGroup.controls.certificateType.value === CertificateType.internal) { + + Certificate will be generated automatically by Cephadm CA for internal certificate type. + +
+ + +
+ @if ( + formGroup.controls.service_type?.value === 'rgw' && + formGroup.controls.virtual_host_enabled?.value + ) { +
+ + Include wildcard certificate for bucket subdomains + + Add wildcard certificates (*.domain) to allow SSL for all bucket subdomains. Required + for virtual-host style with SSL. + + +
+ } + } +
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.spec.ts new file mode 100644 index 00000000000..8c25515ba64 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.spec.ts @@ -0,0 +1,41 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ReactiveFormsModule } from '@angular/forms'; +import { expect as jestExpect } from '@jest/globals'; + +import { CdFormBuilder } from '~/app/shared/forms/cd-form-builder'; +import { CertificateType } from '~/app/shared/models/service.interface'; +import { CertificateAuthorityFormComponent } from './certificate-authority-form.component'; + +describe('CertificateAuthorityFormComponent', () => { + let component: CertificateAuthorityFormComponent; + let fixture: ComponentFixture; + let formBuilder: CdFormBuilder; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ReactiveFormsModule, CertificateAuthorityFormComponent] + }).compileComponents(); + + formBuilder = new CdFormBuilder(); + fixture = TestBed.createComponent(CertificateAuthorityFormComponent); + component = fixture.componentInstance; + component.formGroup = formBuilder.group({ + certificateType: [CertificateType.internal], + custom_sans: [[]], + service_type: ['rgw'], + virtual_host_enabled: [false], + wildcard_enabled: [false] + }); + }); + + it('should create', () => { + fixture.detectChanges(); + jestExpect(component).toBeTruthy(); + }); + + it('should emit certificateTypeChange', () => { + const emitSpy = jest.spyOn(component.certificateTypeChange, 'emit'); + component.onCertificateTypeChange(CertificateType.external); + jestExpect(emitSpy).toHaveBeenCalledWith(CertificateType.external); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.ts new file mode 100644 index 00000000000..f46c92b9103 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/components/certificate-authority-form/certificate-authority-form.component.ts @@ -0,0 +1,47 @@ +import { CommonModule } from '@angular/common'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { ReactiveFormsModule } from '@angular/forms'; +import { CheckboxModule, GridModule, LayoutModule, RadioModule } from 'carbon-components-angular'; + +import { CdFormGroup } from '~/app/shared/forms/cd-form-group'; +import { + CephServiceCertificate, + CertificateType, + CERTIFICATE_STATUS_ICON_MAP +} from '~/app/shared/models/service.interface'; +import { PipesModule } from '~/app/shared/pipes/pipes.module'; +import { ComponentsModule } from '../components.module'; +import { TextLabelListComponent } from '../text-label-list/text-label-list.component'; + +@Component({ + selector: 'cd-certificate-authority-form', + templateUrl: './certificate-authority-form.component.html', + styleUrls: ['./certificate-authority-form.component.scss'], + standalone: true, + imports: [ + CommonModule, + ReactiveFormsModule, + RadioModule, + CheckboxModule, + GridModule, + LayoutModule, + PipesModule, + ComponentsModule, + TextLabelListComponent + ] +}) +export class CertificateAuthorityFormComponent { + readonly CertificateType = CertificateType; + readonly statusIconMap = CERTIFICATE_STATUS_ICON_MAP; + + @Input() formGroup: CdFormGroup; + @Input() editing = false; + @Input() currentCertificate: CephServiceCertificate = null; + @Input() showCertSourceChangeWarning = false; + + @Output() certificateTypeChange = new EventEmitter(); + + onCertificateTypeChange(type: CertificateType): void { + this.certificateTypeChange.emit(type); + } +}