]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Fix auth logic in subsystem and remove traffic encryption columns 67480/head
authorAfreen Misbah <afreen@ibm.com>
Wed, 25 Feb 2026 09:58:12 +0000 (15:28 +0530)
committerAfreen Misbah <afreen@ibm.com>
Mon, 2 Mar 2026 06:33:40 +0000 (12:03 +0530)
Signed-off-by: Afreen Misbah <afreen@ibm.com>
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-initiators-form/nvmeof-initiators-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-initiators-form/nvmeof-initiators-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-initiators-list/nvmeof-initiators-list.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-subsystems-form/nvmeof-subsystem-step-3/nvmeof-subsystem-step-3.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-subsystems-form/nvmeof-subsystem-step-3/nvmeof-subsystem-step-3.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-subsystems-form/nvmeof-subsystem-step-4/nvmeof-subsystem-step-4.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-subsystems-form/nvmeof-subsystems-form.component.html
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-subsystems-form/nvmeof-subsystems-form.component.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/nvmeof-subsystems-form/nvmeof-subsystems-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/components/tearsheet/tearsheet.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/models/nvmeof.ts

index 89d7d6a794b6586f87ec847e3e0a733dd582dd9c..7d50e1a8c56e9891ddfcf00fb8c398ce32fdece0 100644 (file)
@@ -65,7 +65,7 @@ describe('NvmeofInitiatorsFormComponent', () => {
   describe('should test form', () => {
     beforeEach(() => {
       nvmeofService = TestBed.inject(NvmeofService);
-      spyOn(nvmeofService, 'addInitiators').and.stub();
+      spyOn(nvmeofService, 'addSubsystemInitiators').and.stub();
     });
 
     it('should be creating request correctly', () => {
@@ -75,13 +75,15 @@ describe('NvmeofInitiatorsFormComponent', () => {
 
       const payload: any = {
         hostType: HOST_TYPE.SPECIFIC,
-        addedHosts: ['host1']
+        hostDchapKeyList: [{ dhchap_key: '', host_nqn: 'host1' }],
+        gw_group: 'test-group'
       };
 
       component.onSubmit(payload);
-      expect(nvmeofService.addInitiators).toHaveBeenCalledWith(subsystemNQN, {
-        host_nqn: 'host1',
-        gw_group: 'test-group'
+      expect(nvmeofService.addSubsystemInitiators).toHaveBeenCalledWith(subsystemNQN, {
+        allow_all: false,
+        gw_group: 'test-group',
+        hosts: [{ dhchap_key: '', host_nqn: 'host1' }]
       });
     });
   });
index 3876795c10f7a4fcc7778b32bb2c294d4e45b419..d1c0d1fcb121f72baf983f396bbb5712ea2a3839 100644 (file)
@@ -1,6 +1,6 @@
 import { Component, OnInit } from '@angular/core';
 import { Step } from 'carbon-components-angular';
-import { InitiatorRequest, NvmeofService } from '~/app/shared/api/nvmeof.service';
+import { NvmeofService, SubsystemInitiatorRequest } from '~/app/shared/api/nvmeof.service';
 import { FinishedTask } from '~/app/shared/models/finished-task';
 import { HOST_TYPE, NvmeofSubsystemInitiator } from '~/app/shared/models/nvmeof';
 import { TaskWrapperService } from '~/app/shared/services/task-wrapper.service';
@@ -68,8 +68,9 @@ export class NvmeofInitiatorsFormComponent implements OnInit {
     this.isSubmitLoading = true;
     const taskUrl = `nvmeof/initiator/add`;
 
-    const request: InitiatorRequest = {
-      host_nqn: payload.hostType === HOST_TYPE.ALL ? '*' : payload.addedHosts.join(','),
+    const request: SubsystemInitiatorRequest = {
+      allow_all: payload.hostType === HOST_TYPE.ALL,
+      hosts: payload.hostType === HOST_TYPE.SPECIFIC ? payload.hostDchapKeyList : [],
       gw_group: this.group
     };
     this.taskWrapperService
@@ -77,7 +78,7 @@ export class NvmeofInitiatorsFormComponent implements OnInit {
         task: new FinishedTask(taskUrl, {
           nqn: this.subsystemNQN
         }),
-        call: this.nvmeofService.addInitiators(this.subsystemNQN, request)
+        call: this.nvmeofService.addSubsystemInitiators(this.subsystemNQN, request)
       })
       .subscribe({
         error: () => {
index 7152385931cfdc4b830ce4f288123500d9b998a8..2b42b8c339d855cb34a029f70846614749a484e0 100644 (file)
@@ -15,7 +15,7 @@ import { NvmeofInitiatorsListComponent } from './nvmeof-initiators-list.componen
 const mockInitiators = [
   {
     nqn: '*',
-    use_dhchap: ''
+    use_dhchap: false
   }
 ];
 
@@ -82,17 +82,18 @@ describe('NvmeofInitiatorsListComponent', () => {
   }));
 
   it('should update authStatus when initiator has dhchap_key', fakeAsync(() => {
-    const initiatorsWithKey = [{ nqn: 'nqn1', use_dhchap: 'key1' }];
+    const initiatorsWithKey = [{ nqn: 'nqn1', use_dhchap: true }];
     spyOn(TestBed.inject(NvmeofService), 'getInitiators').and.returnValue(of(initiatorsWithKey));
     component.listInitiators();
     tick();
     expect(component.authStatus).toBe('Unidirectional');
   }));
 
-  it('should update authStatus when subsystem has psk', fakeAsync(() => {
-    const subsystemWithPsk = { ...mockSubsystem, has_dhchap_key: true };
-    component.initiators = [{ nqn: 'nqn1', use_dhchap: 'key1' }];
-    spyOn(TestBed.inject(NvmeofService), 'getSubsystem').and.returnValue(of(subsystemWithPsk));
+  it('should update authStatus when subsystem has dhchap_key', fakeAsync(() => {
+    const initiatorsWithKey = [{ nqn: 'nqn1', use_dhchap: true }];
+    component.initiators = initiatorsWithKey;
+    const subsystemWithKey = { ...mockSubsystem, has_dhchap_key: true };
+    spyOn(TestBed.inject(NvmeofService), 'getSubsystem').and.returnValue(of(subsystemWithKey));
     component.getSubsystem();
     tick();
     expect(component.authStatus).toBe('Bi-directional');
index 3eec171ba32e95cac0cc0aa08a1a3377dc89daad..85008935660cc7f2fb1e10291a193b5eaa1c9e20 100644 (file)
@@ -62,7 +62,7 @@
           helperText="A secret key for the subsystem to authenticate itself to hosts."
           i18n-helperText
           [invalid]="subDK.isInvalid"
-          [invalidText]="subsystemDchapKeyInvalidTemplate">
+          [invalidText]="INVALID_TEXTS['required']">
           Subsystem DH-HMAC-CHAP key
           <input cdsPassword
                  cdValidate
         @for (hostDchapKeyItem of hostDchapKeyList.controls; track hostDchapKeyItem.get('host_nqn')?.value; let i = $index) {
         <div [formGroupName]="i">
           <cds-text-label
-            class="cds-mb-3">
+            class="cds-mb-3"
+            [invalid]="hostKey.isInvalid"
+            [invalidText]="INVALID_TEXTS['required']">
             <span
               class="cds-mb-3"
               i18n>DHCHAP Key | {{hostDchapKeyItem.get('host_nqn')?.value }}</span>
             <input cdsPassword
+                   cdValidate
+                   #hostKey="cdValidate"
                    formControlName="dhchap_key"
                    type="password"
                    placeholder="Enter DHCHAP key"
                    class="step-3-form-item"
                    i18n-placeholder
-                   autocomplete>
+                   autocomplete
+                   [invalid]="hostKey.isInvalid">
           </cds-text-label>
         </div>
         }
     </div>
   </div>
 </form>
-
-<ng-template #subsystemDchapKeyInvalidTemplate>
-@for (err of formGroup.get('subsystemDchapKey').errors | keyvalue; track err.key) {
-<span class="invalid-feedback">{{ INVALID_TEXTS[err.key] }}</span>
-}
-</ng-template>
index 4cd4cc110719579bc5f3f724f997f014057b5ebc..ea83d7d5e4a949f469aed8f6c93d71b669462d5b 100644 (file)
@@ -1,9 +1,10 @@
 import { Component, Input, OnInit } from '@angular/core';
-import { FormArray, UntypedFormControl } from '@angular/forms';
+import { FormArray, UntypedFormControl, Validators } from '@angular/forms';
 
 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
-import { AUTHENTICATION, StepTwoType } from '~/app/shared/models/nvmeof';
+import { CdValidators } from '~/app/shared/forms/cd-validators';
+import { AUTHENTICATION, HostStepType } from '~/app/shared/models/nvmeof';
 import { TearsheetStep } from '~/app/shared/models/tearsheet-step';
 
 @Component({
@@ -14,7 +15,7 @@ import { TearsheetStep } from '~/app/shared/models/tearsheet-step';
 })
 export class NvmeofSubsystemsStepThreeComponent implements OnInit, TearsheetStep {
   @Input() group!: string;
-  @Input() set stepTwoValue(value: StepTwoType | null) {
+  @Input() set stepTwoValue(value: HostStepType | null) {
     this._addedHosts = value?.addedHosts ?? [];
     if (this.formGroup) {
       this.syncHostList();
@@ -56,7 +57,11 @@ export class NvmeofSubsystemsStepThreeComponent implements OnInit, TearsheetStep
   private createForm() {
     this.formGroup = new CdFormGroup({
       authType: new UntypedFormControl(AUTHENTICATION.Unidirectional),
-      subsystemDchapKey: new UntypedFormControl(null),
+      subsystemDchapKey: new UntypedFormControl(null, [
+        CdValidators.requiredIf({
+          authType: AUTHENTICATION.Bidirectional
+        })
+      ]),
       hostDchapKeyList: new FormArray([])
     });
 
@@ -65,7 +70,9 @@ export class NvmeofSubsystemsStepThreeComponent implements OnInit, TearsheetStep
 
   private createHostDhchapKeyFormGroup(hostNQN: string = '', key: string | null = null) {
     return new CdFormGroup({
-      dhchap_key: new UntypedFormControl(key),
+      dhchap_key: new UntypedFormControl(key, {
+        validators: [Validators.required]
+      }),
       host_nqn: new UntypedFormControl(hostNQN)
     });
   }
@@ -78,5 +85,9 @@ export class NvmeofSubsystemsStepThreeComponent implements OnInit, TearsheetStep
     return this.formGroup.get('hostDchapKeyList') as FormArray;
   }
 
+  hostDhchapKeyCtrl(i: number) {
+    return (this.hostDchapKeyList.at(i) as CdFormGroup).get('dhchap_key');
+  }
+
   trackByIndex = (i: number) => i;
 }
index b885702a53cae6b8780dd4218176de2e9bbefb69..518b9697847d5e41809dba06c5a21233823c6627 100644 (file)
@@ -3,7 +3,7 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
 
 import { ActionLabelsI18n } from '~/app/shared/constants/app.constants';
 import { CdFormGroup } from '~/app/shared/forms/cd-form-group';
-import { AUTHENTICATION, HOST_TYPE } from '~/app/shared/models/nvmeof';
+import { AUTHENTICATION, HOST_TYPE, NO_AUTH } from '~/app/shared/models/nvmeof';
 import { TearsheetStep } from '~/app/shared/models/tearsheet-step';
 
 @Component({
@@ -45,6 +45,7 @@ export class NvmeofSubsystemsStepFourComponent implements OnInit, TearsheetStep
   }
 
   get authTypeLabel(): string {
+    if (this.authType === AUTHENTICATION.None) return NO_AUTH;
     return this.authType === AUTHENTICATION.Bidirectional
       ? $localize`Bidirectional`
       : $localize`Unidirectional`;
index 6a48e878694f4055bc8432d797c4606b6e775f51..57955f967d00ef628f21558c94666fc710bd5f4a 100644 (file)
@@ -4,12 +4,7 @@
  [description]="description"
  [isSubmitLoading]="isSubmitLoading"
  (submitRequested)="onSubmit($event)"
-<<<<<<< HEAD
- (stepChanged)="populateReviewData()"
-=======
- (stepChanged)="onStepChanged($event)"
->>>>>>> 6d877ea7101 (mgr/dashboard: Allow adding authentication to subsystem flow)
- >
+ (stepChanged)="populateReviewData()">
   <cd-tearsheet-step>
     <cd-nvmeof-subsystem-step-one
      #tearsheetStep
@@ -27,7 +22,7 @@
      [stepTwoValue]="stepTwoValue"
      [group]="group"></cd-nvmeof-subsystem-step-three>
   </cd-tearsheet-step>
-<<<<<<< HEAD
+  }
   <cd-tearsheet-step>
     <cd-nvmeof-subsystem-step-four
      #tearsheetStep
@@ -40,8 +35,5 @@
      [subsystemDchapKey]="reviewSubsystemDchapKey"
      [hostDchapKeyCount]="reviewHostDchapKeyCount"></cd-nvmeof-subsystem-step-four>
   </cd-tearsheet-step>
-=======
-  }
->>>>>>> 6d877ea7101 (mgr/dashboard: Allow adding authentication to subsystem flow)
 </cd-tearsheet>
 
index 5b1f36f472284f47f004eebff3d822cdee3e385c..57185bdc1505f6227d81a5f5dc3009774fd39888 100644 (file)
@@ -93,7 +93,7 @@ describe('NvmeofSubsystemsFormComponent', () => {
     beforeEach(() => {
       nvmeofService = TestBed.inject(NvmeofService);
       spyOn(nvmeofService, 'createSubsystem').and.returnValue(of({}));
-      spyOn(nvmeofService, 'addInitiators').and.returnValue(of({}));
+      spyOn(nvmeofService, 'addSubsystemInitiators').and.returnValue(of({}));
     });
 
     it('should be creating request correctly', () => {
@@ -115,25 +115,17 @@ describe('NvmeofSubsystemsFormComponent', () => {
         addedHosts: [],
         hostType: HOST_TYPE.ALL,
         subsystemDchapKey: 'Q2VwaE52bWVvRkNoYXBTeW50aGV0aWNLZXkxMjM0NTY=',
-<<<<<<< HEAD
-        listeners: []
-=======
+        listeners: [],
         authType: AUTHENTICATION.Bidirectional,
         hostDchapKeyList: []
->>>>>>> 6d877ea7101 (mgr/dashboard: Allow adding authentication to subsystem flow)
       };
 
       component.group = mockGroupName;
       component.onSubmit(payload);
 
-<<<<<<< HEAD
-      expect(nvmeofService.addInitiators).toHaveBeenCalledWith('test-nqn.default', {
-        host_nqn: '*',
-=======
       expect(nvmeofService.addSubsystemInitiators).toHaveBeenCalledWith('test-nqn.default', {
         allow_all: true,
         hosts: [],
->>>>>>> 6d877ea7101 (mgr/dashboard: Allow adding authentication to subsystem flow)
         gw_group: mockGroupName
       });
     });
index 9e3a32fac1980a1ac922be273060295cb0f0342f..3ab7ecd585f5db5f3404befe61785198d1e93a0d 100644 (file)
@@ -7,8 +7,14 @@ import { ActivatedRoute, Router } from '@angular/router';
 import { Step } from 'carbon-components-angular';
 import { NvmeofService, SubsystemInitiatorRequest } from '~/app/shared/api/nvmeof.service';
 import { TearsheetComponent } from '~/app/shared/components/tearsheet/tearsheet.component';
-import { HOST_TYPE, ListenerItem, AUTHENTICATION } from '~/app/shared/models/nvmeof';
-import { AUTHENTICATION, HOST_TYPE, StepTwoType } from '~/app/shared/models/nvmeof';
+import {
+  AUTHENTICATION,
+  HOST_TYPE,
+  HostStepType,
+  ListenerItem,
+  AuthStepType,
+  DetailsStepType
+} from '~/app/shared/models/nvmeof';
 import { from, Observable, of } from 'rxjs';
 import { NotificationService } from '~/app/shared/services/notification.service';
 import { NotificationType } from '~/app/shared/enum/notification-type.enum';
@@ -28,6 +34,13 @@ export type SubsystemPayload = {
 
 type StepResult = { step: string; success: boolean; error?: string };
 
+const STEP_LABELS = {
+  DETAILS: 'Subsystem details',
+  HOSTS: 'Host access control',
+  AUTH: 'Authentication',
+  REVIEW: 'Review'
+} as const;
+
 @Component({
   selector: 'cd-nvmeof-subsystems-form',
   templateUrl: './nvmeof-subsystems-form.component.html',
@@ -42,7 +55,7 @@ export class NvmeofSubsystemsFormComponent implements OnInit {
   description: string = $localize`Subsytems define how hosts connect to NVMe namespaces and ensure secure access to storage.`;
   isSubmitLoading: boolean = false;
   private lastCreatedNqn: string;
-  stepTwoValue: StepTwoType = null;
+  stepTwoValue: HostStepType = null;
   showAuthStep = true;
 
   @ViewChild(TearsheetComponent) tearsheet!: TearsheetComponent;
@@ -74,53 +87,61 @@ export class NvmeofSubsystemsFormComponent implements OnInit {
     this.rebuildSteps();
   }
 
+  private setAuthStepVisibility(nextShowAuth: boolean) {
+    if (this.showAuthStep === nextShowAuth) return;
+    this.showAuthStep = nextShowAuth;
+    this.rebuildSteps();
+  }
+
   populateReviewData() {
-    if (!this.tearsheet?.stepContents) return;
-    const steps = this.tearsheet.stepContents.toArray();
-
-    // Step 1: Subsystem details
-    const step1Form = steps[0]?.stepComponent?.formGroup;
-    if (step1Form) {
-      this.reviewNqn = step1Form.get('nqn')?.value || '';
-      this.reviewListeners = step1Form.get('listeners')?.value || [];
+    if (!this.tearsheet) return;
+
+    const step1 = this.tearsheet.getStepValueByLabel<DetailsStepType>(STEP_LABELS.DETAILS);
+    const step2 = this.tearsheet.getStepValueByLabel<HostStepType>(STEP_LABELS.HOSTS);
+
+    if (step1) {
+      this.reviewNqn = step1.nqn ?? '';
+      this.reviewListeners = step1.listeners ?? [];
     }
 
-    // Step 2: Host access control
-    const step2Form = steps[1]?.stepComponent?.formGroup;
-    if (step2Form) {
-      this.reviewHostType = step2Form.get('hostType')?.value || HOST_TYPE.SPECIFIC;
-      this.reviewAddedHosts = step2Form.get('addedHosts')?.value || [];
+    if (step2) {
+      this.reviewHostType = step2.hostType ?? HOST_TYPE.SPECIFIC;
+      this.reviewAddedHosts = step2.addedHosts ?? [];
+      this.stepTwoValue = step2;
     }
 
-    // Step 3: Authentication
-    const step3Form = steps[2]?.stepComponent?.formGroup;
-    if (step3Form) {
-      this.reviewAuthType = step3Form.get('authType')?.value || AUTHENTICATION.Unidirectional;
-      this.reviewSubsystemDchapKey = step3Form.get('subsystemDchapKey')?.value || '';
-      const hostKeys = step3Form.get('hostDchapKeyList')?.value || [];
-      this.reviewHostDchapKeyCount = hostKeys.filter((k: any) => k?.key).length;
-  
-      }  }
-  onStepChanged(_e: { current: number }) {
-    const stepTwo = this.tearsheet?.getStepValue(1);
-    this.stepTwoValue = stepTwo;
-
-    this.showAuthStep = stepTwo?.hostType !== HOST_TYPE.ALL;
+    const nextShowAuth = (step2?.hostType ?? HOST_TYPE.SPECIFIC) === HOST_TYPE.SPECIFIC;
 
-    this.rebuildSteps();
+    if (nextShowAuth !== this.showAuthStep) {
+      this.setAuthStepVisibility(nextShowAuth);
+      return;
+    }
+
+    const authStep = this.tearsheet.getStepValueByLabel<AuthStepType>(STEP_LABELS.AUTH);
+
+    if (this.showAuthStep && authStep) {
+      this.reviewAuthType = authStep.authType ?? AUTHENTICATION.Unidirectional;
+      this.reviewSubsystemDchapKey = authStep.subsystemDchapKey ?? '';
+      const hostKeyList = authStep.hostDchapKeyList ?? [];
+      this.reviewHostDchapKeyCount = hostKeyList.filter((item) => !!item?.dhchap_key)?.length;
+    } else {
+      this.reviewAuthType = null;
+      this.reviewSubsystemDchapKey = '';
+      this.reviewHostDchapKeyCount = 0;
+    }
   }
 
   rebuildSteps() {
     const steps: Step[] = [
-      { label: 'Subsystem details', invalid: false },
-      { label: 'Host access control', invalid: false }
+      { label: STEP_LABELS.DETAILS, invalid: false },
+      { label: STEP_LABELS.HOSTS, invalid: false }
     ];
 
     if (this.showAuthStep) {
-      steps.push({ label: 'Authentication', invalid: false });
+      steps.push({ label: STEP_LABELS.AUTH, invalid: false });
     }
 
-    steps.push({ label: 'Review', invalid: false });
+    steps.push({ label: STEP_LABELS.REVIEW, invalid: false });
 
     this.steps = steps;
 
@@ -165,7 +186,10 @@ export class NvmeofSubsystemsFormComponent implements OnInit {
           sequentialSteps.push({
             step: this.steps[1].label,
             call: () =>
-              this.nvmeofService.addInitiators(`${payload.nqn}.${this.group}`, initiatorRequest)
+              this.nvmeofService.addSubsystemInitiators(
+                `${payload.nqn}.${this.group}`,
+                initiatorRequest
+              )
           });
 
           this.runSequentialSteps(sequentialSteps, stepResults).subscribe({
index c3806ea0920700edef1fd17fd8379326459b4546..99fdbfa1f200050e45ad770dc35fcf36e66c5392 100644 (file)
@@ -90,6 +90,16 @@ export class TearsheetComponent implements OnInit, AfterViewInit, OnDestroy {
     return wrapper?.stepComponent?.formGroup?.value ?? null;
   }
 
+  getStepIndexByLabel(label: string): number {
+    return this.steps?.findIndex((s) => s.label === label) ?? -1;
+  }
+
+  getStepValueByLabel<T = any>(label: string): T | null {
+    const idx = this.getStepIndexByLabel(label);
+    if (idx < 0) return null;
+    return this.getStepValue<T>(idx);
+  }
+
   currentStep: number = 0;
   lastStep: number = null;
   isOpen: boolean = true;
@@ -160,7 +170,7 @@ export class TearsheetComponent implements OnInit, AfterViewInit, OnDestroy {
   }
 
   handleSubmit() {
-    if (this.steps[this.currentStep].invalid) return;
+    if (this.steps.some((step) => step?.invalid)) return;
 
     const mergedPayloads = this.getMergedPayload();
 
index 5107b671578e56900e3b5d413b23f09eb0e41e76..11d7edab3b0e8b5a4cb33d2077b7faf0838fbf31 100644 (file)
@@ -33,7 +33,7 @@ export interface NvmeofSubsystemData extends NvmeofSubsystem {
 
 export interface NvmeofSubsystemInitiator {
   nqn: string;
-  use_dhchap?: string;
+  use_dhchap?: boolean;
 }
 
 export interface NvmeofListener {
@@ -74,9 +74,12 @@ export interface NvmeofGatewayGroup extends CephServiceSpec {
 
 export enum AUTHENTICATION {
   Unidirectional = 'unidirectional',
-  Bidirectional = 'bidirectional'
+  Bidirectional = 'bidirectional',
+  None = 'none'
 }
 
+export const NO_AUTH = 'No authentication';
+
 export const HOST_TYPE = {
   ALL: 'all',
   SPECIFIC: 'specific'
@@ -96,10 +99,11 @@ export function getSubsystemAuthStatus(
   _initiators: NvmeofSubsystemInitiator[] | { hosts?: NvmeofSubsystemInitiator[] }
 ): string {
   // Import enum value strings to avoid circular dependency
-  const NO_AUTH = 'No authentication';
   const UNIDIRECTIONAL = 'Unidirectional';
   const BIDIRECTIONAL = 'Bi-directional';
 
+  let auth = NO_AUTH;
+
   let hostsList: NvmeofSubsystemInitiator[] = [];
   if (_initiators && 'hosts' in _initiators && Array.isArray(_initiators.hosts)) {
     hostsList = _initiators.hosts;
@@ -107,8 +111,6 @@ export function getSubsystemAuthStatus(
     hostsList = _initiators as NvmeofSubsystemInitiator[];
   }
 
-  let auth = NO_AUTH;
-
   const hostHasDhchapKey = hostsList.some((host) => !!host.use_dhchap);
 
   if (hostHasDhchapKey) {
@@ -149,8 +151,22 @@ export type NvmeofInitiatorCandidate = {
   selected: boolean;
 };
 
-export type StepTwoType = {
+export type HostStepType = {
   addedHosts: Array<string>;
   hostname: string;
   hostType: string;
 };
+
+export type AuthStepType = {
+  authType: AUTHENTICATION;
+  subsystemDchapKey: string;
+  hostDchapKeyList: Array<{
+    dhchap_key: string;
+    host_nqn: string;
+  }>;
+};
+
+export type DetailsStepType = {
+  nqn: string;
+  listeners: Array<string>;
+};