name="pool"
class="form-select"
formControlName="pool"
- (change)="onBlockPoolChange()">
+ (change)="setNvmeServiceId()">
<option *ngIf="rbdPools === null"
[ngValue]="null"
i18n>Loading...</option>
class="form-control"
type="text"
formControlName="group"
- (change)="onNvmeofGroupChange($event.target.value)">
+ (change)="setNvmeServiceId()">
</div>
<cd-help-text i18n>
The name of the gateway group.
i18n>
Modifying the default settings could lead to a weaker security configuration
</cd-alert-panel>
+
+ <!-- NVMe/TCP -->
+ <!-- mTLS -->
+ <div class="form-group row"
+ *ngIf="serviceForm.controls.service_type.value === 'nvmeof'">
+ <div class="cd-col-form-offset">
+ <div class="custom-control custom-checkbox">
+ <input class="custom-control-input"
+ id="enable_mtls"
+ type="checkbox"
+ formControlName="enable_mtls">
+ <label class="custom-control-label"
+ for="enable_mtls"
+ i18n>Encryption</label>
+ <cd-help-text i18n>Enables mutual TLS (mTLS) between the client and the gateway server.</cd-help-text>
+ </div>
+ </div>
+ </div>
+
+ <!-- root_ca_cert -->
+ <div *ngIf="serviceForm.controls.enable_auth.value"
+ class="form-group row">
+ <label class="cd-col-form-label required"
+ for="root_ca_cert">
+ <span i18n>Root CA certificate</span>
+ </label>
+ <div class="cd-col-form-input">
+ <textarea id="root_ca_cert"
+ class="form-control resize-vertical text-monospace text-pre"
+ formControlName="root_ca_cert"
+ rows="5"></textarea>
+ <input type="file"
+ (change)="fileUpload($event.target.files, 'root_ca_cert')">
+ <span class="invalid-feedback"
+ *ngIf="serviceForm.showError('root_ca_cert', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- client_cert -->
+ <div *ngIf="serviceForm.controls.enable_auth.value"
+ class="form-group row">
+ <label class="cd-col-form-label required"
+ for="client_cert">
+ <span i18n>Client CA certificate</span>
+ </label>
+ <div class="cd-col-form-input">
+ <textarea id="client_cert"
+ class="form-control resize-vertical text-monospace text-pre"
+ formControlName="client_cert"
+ rows="5"></textarea>
+ <input type="file"
+ (change)="fileUpload($event.target.files, 'client_cert')">
+ <span class="invalid-feedback"
+ *ngIf="serviceForm.showError('client_cert', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- client_key -->
+ <div *ngIf="serviceForm.controls.enable_auth.value"
+ class="form-group row">
+ <label class="cd-col-form-label required"
+ for="client_key">
+ <span i18n>Client key</span>
+ </label>
+ <div class="cd-col-form-input">
+ <textarea id="client_key"
+ class="form-control resize-vertical text-monospace text-pre"
+ formControlName="client_key"
+ rows="5"></textarea>
+ <input type="file"
+ (change)="fileUpload($event.target.files, 'client_key')">
+ <span class="invalid-feedback"
+ *ngIf="serviceForm.showError('client_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- server_cert -->
+ <div *ngIf="serviceForm.controls.enable_auth.value"
+ class="form-group row">
+ <label class="cd-col-form-label required"
+ for="server_cert">
+ <span i18n>Gateway server certificate</span>
+ </label>
+ <div class="cd-col-form-input">
+ <textarea id="server_cert"
+ class="form-control resize-vertical text-monospace text-pre"
+ formControlName="server_cert"
+ rows="5"></textarea>
+ <input type="file"
+ (change)="fileUpload($event.target.files, 'server_cert')">
+ <span class="invalid-feedback"
+ *ngIf="serviceForm.showError('server_cert', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
+ <!-- server_key -->
+ <div *ngIf="serviceForm.controls.enable_auth.value"
+ class="form-group row">
+ <label class="cd-col-form-label required"
+ for="server_key">
+ <span i18n>Gateway server key</span>
+ </label>
+ <div class="cd-col-form-input">
+ <textarea id="server_key"
+ class="form-control resize-vertical text-monospace text-pre"
+ formControlName="server_key"
+ rows="5"></textarea>
+ <input type="file"
+ (change)="fileUpload($event.target.files, 'server_key')">
+ <span class="invalid-feedback"
+ *ngIf="serviceForm.showError('server_key', frm, 'required')"
+ i18n>This field is required.</span>
+ </div>
+ </div>
+
</div>
<div class="modal-footer">
expect(countEl).toBeNull();
});
- it('should submit nvmeof', () => {
+ it('should not show certs and keys field with mTLS disabled', () => {
+ formHelper.setValue('ssl', true);
+ fixture.detectChanges();
+ const root_ca_cert = fixture.debugElement.query(By.css('#root_ca_cert'));
+ const client_cert = fixture.debugElement.query(By.css('#client_cert'));
+ const client_key = fixture.debugElement.query(By.css('#client_key'));
+ const server_cert = fixture.debugElement.query(By.css('#server_cert'));
+ const server_key = fixture.debugElement.query(By.css('#server_key'));
+ expect(root_ca_cert).toBeNull();
+ expect(client_cert).toBeNull();
+ expect(client_key).toBeNull();
+ expect(server_cert).toBeNull();
+ expect(server_key).toBeNull();
+ });
+
+ it('should submit nvmeof without mTLS', () => {
+ component.onSubmit();
+ expect(cephServiceService.create).toHaveBeenCalledWith({
+ service_type: 'nvmeof',
+ service_id: 'rbd.default',
+ placement: {},
+ unmanaged: false,
+ pool: 'rbd',
+ group: 'default',
+ enable_auth: false
+ });
+ });
+
+ it('should submit nvmeof with mTLS', () => {
+ formHelper.setValue('enable_mtls', true);
+ formHelper.setValue('root_ca_cert', 'root_ca_cert');
+ formHelper.setValue('client_cert', 'client_cert');
+ formHelper.setValue('client_key', 'client_key');
+ formHelper.setValue('server_cert', 'server_cert');
+ formHelper.setValue('server_key', 'server_key');
component.onSubmit();
expect(cephServiceService.create).toHaveBeenCalledWith({
service_type: 'nvmeof',
placement: {},
unmanaged: false,
pool: 'rbd',
- group: 'default'
+ group: 'default',
+ enable_auth: true,
+ root_ca_cert: 'root_ca_cert',
+ client_cert: 'client_cert',
+ client_key: 'client_key',
+ server_cert: 'server_cert',
+ server_key: 'server_key'
});
});
});
const groupId = fixture.debugElement.query(By.css('#group')).nativeElement;
expect(groupId.disabled).toBeTruthy();
});
+
+ it('should update nvmeof service to disable mTLS', () => {
+ spyOn(cephServiceService, 'update').and.stub();
+ component.serviceType = 'nvmeof';
+ formHelper.setValue('service_type', 'nvmeof');
+ formHelper.setValue('pool', 'rbd');
+ formHelper.setValue('group', 'default');
+ // mTLS disabled
+ formHelper.setValue('enable_auth', false);
+ component.onSubmit();
+ expect(cephServiceService.update).toHaveBeenCalledWith({
+ service_type: 'nvmeof',
+ placement: {},
+ unmanaged: false,
+ pool: 'rbd',
+ group: 'default',
+ enable_auth: false
+ });
+ });
});
});
});
service_type: 'nvmeof'
})
],
+ enable_mtls: [false],
+ root_ca_cert: [
+ null,
+ [
+ CdValidators.composeIf(
+ {
+ service_type: 'nvmeof',
+ enable_mtls: true
+ },
+ [Validators.required]
+ )
+ ]
+ ],
+ client_cert: [
+ null,
+ [
+ CdValidators.composeIf(
+ {
+ service_type: 'nvmeof',
+ enable_mtls: true
+ },
+ [Validators.required]
+ )
+ ]
+ ],
+ client_key: [
+ null,
+ [
+ CdValidators.composeIf(
+ {
+ service_type: 'nvmeof',
+ enable_mtls: true
+ },
+ [Validators.required]
+ )
+ ]
+ ],
+ server_cert: [
+ null,
+ [
+ CdValidators.composeIf(
+ {
+ service_type: 'nvmeof',
+ enable_mtls: true
+ },
+ [Validators.required]
+ )
+ ]
+ ],
+ server_key: [
+ null,
+ [
+ CdValidators.composeIf(
+ {
+ service_type: 'nvmeof',
+ enable_mtls: true
+ },
+ [Validators.required]
+ )
+ ]
+ ],
// RGW
rgw_frontend_port: [null, [CdValidators.number(false)]],
realm_name: [null],
case 'nvmeof':
this.serviceForm.get('pool').setValue(response[0].spec.pool);
this.serviceForm.get('group').setValue(response[0].spec.group);
+ this.serviceForm.get('enable_auth').setValue(response[0].spec.enable_auth);
+ this.serviceForm.get('root_ca_cert').setValue(response[0].spec.root_ca_cert);
+ this.serviceForm.get('client_cert').setValue(response[0].spec.client_cert);
+ this.serviceForm.get('client_key').setValue(response[0].spec.client_key);
+ this.serviceForm.get('server_cert').setValue(response[0].spec.server_cert);
+ this.serviceForm.get('server_key').setValue(response[0].spec.server_key);
break;
case 'rgw':
this.serviceForm
);
}
- onNvmeofGroupChange(groupName: string) {
+ setNvmeServiceId() {
const pool = this.serviceForm.get('pool').value;
- if (pool) this.serviceForm.get('service_id').setValue(`${pool}.${groupName}`);
- else this.serviceForm.get('service_id').setValue(groupName);
- }
-
- getDefaultBlockPool(): string {
- // returns 'rbd' pool otherwise the first block pool
- return (
- this.rbdPools?.find((p: Pool) => p.pool_name === 'rbd')?.pool_name ||
- this.rbdPools?.[0].pool_name
- );
- }
-
- setNvmeofServiceIdAndPool(): void {
- const defaultBlockPool: string = this.getDefaultBlockPool();
- const group: string = this.serviceForm.get('group').value;
- if (defaultBlockPool && group) {
- this.serviceForm.get('pool').setValue(defaultBlockPool);
- this.serviceForm.get('service_id').setValue(`${defaultBlockPool}.${group}`);
+ const group = this.serviceForm.get('group').value;
+ if (pool && group) {
+ this.serviceForm.get('service_id').setValue(`${pool}.${group}`);
+ } else if (pool) {
+ this.serviceForm.get('service_id').setValue(pool);
+ } else if (group) {
+ this.serviceForm.get('service_id').setValue(group);
} else {
this.serviceForm.get('service_id').setValue(null);
}
}
+ setNvmeDefaultPool() {
+ const defaultPool =
+ this.rbdPools?.find((p: Pool) => p.pool_name === 'rbd')?.pool_name ||
+ this.rbdPools?.[0].pool_name;
+ this.serviceForm.get('pool').setValue(defaultPool);
+ }
+
requiresServiceId(serviceType: string) {
return ['mds', 'rgw', 'nfs', 'iscsi', 'nvmeof', 'smb', 'ingress'].includes(serviceType);
}
setServiceId(serviceId: string): void {
const requiresServiceId: boolean = this.requiresServiceId(serviceId);
if (requiresServiceId && serviceId === 'nvmeof') {
- this.setNvmeofServiceIdAndPool();
+ this.setNvmeDefaultPool();
+ this.setNvmeServiceId();
} else if (requiresServiceId) {
this.serviceForm.get('service_id').setValue(null);
} else {
}
}
- onBlockPoolChange() {
- const selectedBlockPool = this.serviceForm.get('pool').value;
- const group = this.serviceForm.get('group').value;
- if (selectedBlockPool && group) {
- this.serviceForm.get('service_id').setValue(`${selectedBlockPool}.${group}`);
- } else if (selectedBlockPool) {
- this.serviceForm.get('service_id').setValue(selectedBlockPool);
- } else {
- this.serviceForm.get('service_id').setValue(null);
- }
- }
-
disableForEditing(serviceType: string) {
const disableForEditKeys = ['service_type', 'service_id'];
disableForEditKeys.forEach((key) => {
case 'nvmeof':
serviceSpec['pool'] = values['pool'];
serviceSpec['group'] = values['group'];
+ serviceSpec['enable_auth'] = values['enable_mtls'];
+ if (values['enable_mtls']) {
+ serviceSpec['root_ca_cert'] = values['root_ca_cert'];
+ serviceSpec['client_cert'] = values['client_cert'];
+ serviceSpec['client_key'] = values['client_key'];
+ serviceSpec['server_cert'] = values['server_cert'];
+ serviceSpec['server_key'] = values['server_key'];
+ }
break;
case 'iscsi':
serviceSpec['pool'] = values['pool'];
expectedChange(
{
poolDetails: {
+ application_metadata: ['rbd'],
pg_num: 256,
pg_num_target: 256,
pg_placement_num: 256,
virtual_interface_networks: string[];
pool: string;
group: string;
+ root_ca_cert: string;
+ client_cert: string;
+ client_key: string;
+ server_cert: string;
+ server_key: string;
rgw_frontend_ssl_certificate: string;
ssl: boolean;
ssl_cert: string;