Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 3 additions & 33 deletions oas_docs/output/kibana.serverless.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -89762,17 +89762,8 @@ components:
- none
type: string
compression_level:
anyOf:
- items: {}
type: array
- type: boolean
- type: number
- type: object
- type: string
nullable: true
oneOf:
- type: number
- not: {}
type: number
config_yaml:
nullable: true
type: string
Expand Down Expand Up @@ -90028,7 +90019,6 @@ components:
- name
- type
- hosts
- compression_level
- auth_type
- connection_type
- username
Expand Down Expand Up @@ -91239,17 +91229,8 @@ components:
- none
type: string
compression_level:
anyOf:
- items: {}
type: array
- type: boolean
- type: number
- type: object
- type: string
nullable: true
oneOf:
- type: number
- not: {}
type: number
config_yaml:
nullable: true
type: string
Expand Down Expand Up @@ -91505,7 +91486,6 @@ components:
- name
- type
- hosts
- compression_level
- auth_type
- connection_type
- username
Expand Down Expand Up @@ -93705,17 +93685,8 @@ components:
- none
type: string
compression_level:
anyOf:
- items: {}
type: array
- type: boolean
- type: number
- type: object
- type: string
nullable: true
oneOf:
- type: number
- not: {}
type: number
config_yaml:
nullable: true
type: string
Expand Down Expand Up @@ -93969,7 +93940,6 @@ components:
type: string
required:
- name
- compression_level
- connection_type
- username
- password
Expand Down
36 changes: 3 additions & 33 deletions oas_docs/output/kibana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100928,17 +100928,8 @@ components:
- none
type: string
compression_level:
anyOf:
- items: {}
type: array
- type: boolean
- type: number
- type: object
- type: string
nullable: true
oneOf:
- type: number
- not: {}
type: number
config_yaml:
nullable: true
type: string
Expand Down Expand Up @@ -101194,7 +101185,6 @@ components:
- name
- type
- hosts
- compression_level
- auth_type
- connection_type
- username
Expand Down Expand Up @@ -102405,17 +102395,8 @@ components:
- none
type: string
compression_level:
anyOf:
- items: {}
type: array
- type: boolean
- type: number
- type: object
- type: string
nullable: true
oneOf:
- type: number
- not: {}
type: number
config_yaml:
nullable: true
type: string
Expand Down Expand Up @@ -102671,7 +102652,6 @@ components:
- name
- type
- hosts
- compression_level
- auth_type
- connection_type
- username
Expand Down Expand Up @@ -104871,17 +104851,8 @@ components:
- none
type: string
compression_level:
anyOf:
- items: {}
type: array
- type: boolean
- type: number
- type: object
- type: string
nullable: true
oneOf:
- type: number
- not: {}
type: number
config_yaml:
nullable: true
type: string
Expand Down Expand Up @@ -105135,7 +105106,6 @@ components:
type: string
required:
- name
- compression_level
- connection_type
- username
- password
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ export {
// Cloud Connector accessor module
export * from './cloud_connectors';

export { validateSslCertPath } from './ssl_validators';

export {
packageInfoHasOtelInputs,
packagePolicyHasOtelInputs,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { validateSslCertPath } from './ssl_validators';

describe('validateSslCertPath', () => {
describe('valid inputs (returns undefined)', () => {
it('empty string', () => {
expect(validateSslCertPath('')).toBeUndefined();
});

it('Linux path without spaces', () => {
expect(validateSslCertPath('/etc/certs/ca.pem')).toBeUndefined();
});

it('relative path without spaces', () => {
expect(validateSslCertPath('./certs/ca.pem')).toBeUndefined();
});

it('Windows absolute path without spaces', () => {
expect(validateSslCertPath('C:\\certs\\server.pem')).toBeUndefined();
});

it('Windows forward-slash path without spaces', () => {
expect(validateSslCertPath('C:/certs/server.pem')).toBeUndefined();
});

it('UNC path without spaces', () => {
expect(validateSslCertPath('\\\\server\\share\\cert.pem')).toBeUndefined();
});

it('PEM certificate content', () => {
expect(
validateSslCertPath(
'-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWgAwIBAgIJAJC1\n-----END CERTIFICATE-----'
)
).toBeUndefined();
});

it('PEM RSA private key', () => {
expect(
validateSslCertPath(
'-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA\n-----END RSA PRIVATE KEY-----'
)
).toBeUndefined();
});

it('PEM EC private key', () => {
expect(
validateSslCertPath(
'-----BEGIN EC PRIVATE KEY-----\nMHQCAQEEIO\n-----END EC PRIVATE KEY-----'
)
).toBeUndefined();
});

it('PEM content with leading whitespace', () => {
expect(
validateSslCertPath(' -----BEGIN CERTIFICATE-----\nMIID\n-----END CERTIFICATE-----')
).toBeUndefined();
});
});

describe('invalid inputs (returns error string)', () => {
it('Linux path with spaces', () => {
expect(validateSslCertPath('/path/to my cert.pem')).toBeDefined();
});

it('relative path with spaces', () => {
expect(validateSslCertPath('./my certs/ca.pem')).toBeDefined();
});

it('Windows path with spaces', () => {
expect(validateSslCertPath('C:\\Program Files\\certs\\server.pem')).toBeDefined();
});

it('Windows forward-slash path with spaces', () => {
expect(validateSslCertPath('C:/Program Files/certs/server.pem')).toBeDefined();
});

it('UNC path with spaces in share name', () => {
expect(validateSslCertPath('\\\\server\\my share\\cert.pem')).toBeDefined();
});

it('path with tab character', () => {
expect(validateSslCertPath('/path/to\tcert.pem')).toBeDefined();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { i18n } from '@kbn/i18n';

// PEM content (-----BEGIN ...) is exempt — it naturally contains whitespace
export function validateSslCertPath(value: string): string | undefined {
if (!value || value.trimStart().startsWith('-----BEGIN')) return undefined;
if (/\s/.test(value)) {
return i18n.translate('xpack.fleet.sslValidation.pathSpacesError', {
defaultMessage: 'SSL certificate path cannot contain whitespace',
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export interface KafkaOutput extends NewBaseOutput {
version?: string;
key?: string;
compression?: ValueOf<KafkaCompressionType>;
compression_level?: number;
compression_level?: number | null;
auth_type?: ValueOf<KafkaAuthType>;
connection_type?: ValueOf<KafkaConnectionTypeType>;
username?: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,12 @@ describe('Edit settings', () => {
cy.getBySel(SETTINGS_OUTPUTS.TYPE_INPUT).select('logstash');
cy.get('[placeholder="Specify host"').clear().type('logstash:5044');
cy.getBySel(SETTINGS_OUTPUTS.SSL_BUTTON).click();
cy.get('[placeholder="Specify SSL certificate"]').clear().type('SSL CERTIFICATE');
cy.get('[placeholder="Specify certificate key"]').clear().type('SSL KEY');
cy.get('[placeholder="Specify SSL certificate"]')
.clear()
.type('-----BEGIN CERTIFICATE-----', { parseSpecialCharSequences: false });
cy.get('[placeholder="Specify certificate key"]')
.clear()
.type('-----BEGIN PRIVATE KEY-----', { parseSpecialCharSequences: false });

cy.intercept('/api/fleet/outputs', {
items: [
Expand All @@ -157,8 +161,8 @@ describe('Edit settings', () => {
is_default: false,
is_default_monitoring: false,
ssl: {
certificate: "SSL CERTIFICATE');",
key: 'SSL KEY',
certificate: '-----BEGIN CERTIFICATE-----',
key: '-----BEGIN PRIVATE KEY-----',
},
}).as('postLogstashOutput');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,11 @@ queue:
describe('Remote ES', () => {
it('displays proper error messages', () => {
selectRemoteESOutput();
cy.getBySel(SETTINGS_OUTPUTS.NAME_INPUT).type('name');
cy.get('[placeholder="Specify host URL"').clear().type('https://localhost:5000');
cy.getBySel(SETTINGS_SAVE_BTN).click();

cy.contains('Name is required');
cy.contains('URL is required');
cy.contains('Service token is required');
shouldDisplayError(SETTINGS_OUTPUTS.NAME_INPUT);
shouldDisplayError('serviceTokenSecretInput');
});

Expand Down Expand Up @@ -392,18 +391,17 @@ queue:

it('displays proper error messages', () => {
selectKafkaOutput();
cy.getBySel(SETTINGS_OUTPUTS.NAME_INPUT).type('name');
cy.get('[placeholder="Specify host"').type('localhost:5000');
cy.getBySel(SETTINGS_OUTPUTS_KAFKA.HEADERS_CLIENT_ID_INPUT).clear();
cy.getBySel(SETTINGS_SAVE_BTN).click();

cy.contains('Name is required');
cy.contains('Host is required');
cy.contains('Username is required');
cy.contains('Password is required');
cy.contains('Default topic is required');
cy.contains(
'Client ID is invalid. Only letters, numbers, dots, underscores, and dashes are allowed.'
);
shouldDisplayError(SETTINGS_OUTPUTS.NAME_INPUT);
shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_USERNAME_INPUT);
shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.AUTHENTICATION_PASSWORD_INPUT);
shouldDisplayError(SETTINGS_OUTPUTS_KAFKA.TOPICS_DEFAULT_TOPIC_INPUT);
Expand Down Expand Up @@ -564,8 +562,12 @@ queue:
cy.get('[placeholder="Specify host"').clear().type('localhost:5000');

cy.getBySel(SETTINGS_OUTPUTS.SSL_BUTTON).click();
cy.get('[placeholder="Specify SSL certificate"]').clear().type('SSL CERTIFICATE');
cy.get('[placeholder="Specify certificate key"]').clear().type('SSL KEY');
cy.get('[placeholder="Specify SSL certificate"]')
.clear()
.type('-----BEGIN CERTIFICATE-----', { parseSpecialCharSequences: false });
cy.get('[placeholder="Specify certificate key"]')
.clear()
.type('-----BEGIN PRIVATE KEY-----', { parseSpecialCharSequences: false });

cy.intercept('PUT', '**/api/fleet/outputs/**').as('saveOutput');

Expand Down
Loading
Loading