Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
999a7aa
first commit
jcger Jun 4, 2025
69fbd57
make the new provider conf optional
jcger Jun 4, 2025
6563e31
fix tests
jcger Jun 5, 2025
b7dc42e
Merge branch 'main' into issue-220416-kbn-config-disable-ptx-files
jcger Jun 6, 2025
431decf
Merge branch 'main' into issue-220416-kbn-config-disable-ptx-files
jcger Jun 6, 2025
b12211c
create connector api rejects if pfx disabled
jcger Jun 9, 2025
40a432b
add action_config mock fn
jcger Jun 9, 2025
57b197f
Merge branch 'main' of github.com:jcger/kibana into issue-220416-kbn-…
jcger Jun 9, 2025
d981181
use i18 values
jcger Jun 9, 2025
ac2029d
Merge branch 'main' of github.com:jcger/kibana into issue-220416-kbn-…
jcger Jun 10, 2025
30c49aa
remove unnecessesary config param
jcger Jun 10, 2025
2694031
pfx setting only affects webhook connector now
jcger Jun 12, 2025
4814a1b
Merge branch 'main' of github.com:jcger/kibana into issue-220416-kbn-…
jcger Jun 13, 2025
758fd3e
fix tests + error message
jcger Jun 13, 2025
082d23b
rename to xpack.actions.webhook.ssl.pfx.enabled
jcger Jun 13, 2025
aa039cb
fix functional test
jcger Jun 13, 2025
e38706e
Merge branch 'main' into issue-220416-kbn-config-disable-ptx-files
jcger Jun 16, 2025
692ba3d
Update docs/reference/configuration-reference/alerting-settings.md
jcger Jun 17, 2025
da94d02
Update docs/reference/configuration-reference/alerting-settings.md
jcger Jun 17, 2025
f165763
Update docs/settings-gen/source/kibana-alert-action-settings.yml
jcger Jun 17, 2025
a88508e
Merge branch 'main' into issue-220416-kbn-config-disable-ptx-files
jcger Jun 17, 2025
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
1 change: 1 addition & 0 deletions .buildkite/ftr_platform_stateful_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ enabled:
- x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/config.ts
- x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/with_aws_ses_kibana_config/config.ts
- x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/shared/config.ts
- x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/webhook_disabled_ssl_pfx/config.ts
- x-pack/test/functional/apps/advanced_settings/config.ts
- x-pack/test/functional/apps/aiops/config.ts
- x-pack/test/functional/apps/api_keys/config.ts
Expand Down
6 changes: 6 additions & 0 deletions docs/reference/configuration-reference/alerting-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,12 @@ For more examples, go to [Preconfigured connectors](/reference/connectors-kibana

Data type: `string`

`xpack.actions.webhook.ssl.pfx.enabled`
: Disable PFX file support for SSL client authentication. When set to `false`, the application will not accept PFX certificate files and will require separate certificate and private key files instead. Only applies to the [Webhook connector](/reference/connectors-kibana/webhook-action-type.md).

Data type: `bool`
Comment thread
jcger marked this conversation as resolved.
Default: `true`

## Alerting settings [alert-settings]

`xpack.alerting.cancelAlertsOnRuleTimeout` ![logo cloud](https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg "Supported on {{ech}}")
Expand Down
21 changes: 21 additions & 0 deletions docs/settings-gen/source/kibana-alert-action-settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2303,6 +2303,27 @@ groups:
self: all
# example: |

- setting: xpack.actions.webhook.ssl.pfx.enabled
# id:
description: |
Disable PFX file support for SSL client authentication. When set to `false`, the application will not accept PFX certificate files and will require separate certificate and private key files instead. Only applies to the [Webhook connector](/reference/connectors-kibana/webhook-action-type.md).
# state: deprecated/hidden/tech-preview
# deprecation_details: ""
# note: ""
# tip: ""
# warning: ""
# important: ""
datatype: bool
default: true
# options:
# - option:
# description: ""
# type: static/dynamic
applies_to:
deployment:
self: all
# example: |

- group: Alerting settings
id: alert-settings
# description: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ kibana_vars=(
xpack.actions.responseTimeout
xpack.actions.ssl.proxyVerificationMode
xpack.actions.ssl.verificationMode
xpack.actions.webhook.ssl.pfx.enabled
xpack.alerting.healthCheck.interval
xpack.alerting.invalidateApiKeysTask.interval
xpack.alerting.invalidateApiKeysTask.removalDelay
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'vis_type_xy.readOnly (boolean?|never)',
'vis_type_vega.enableExternalUrls (boolean?)',
'xpack.actions.email.domain_allowlist (array?)',
'xpack.actions.webhook.ssl.pfx.enabled (boolean?)',
'xpack.apm.serviceMapEnabled (boolean?)',
'xpack.apm.ui.enabled (boolean?)',
'xpack.apm.ui.maxTraceItems (number?)',
Expand Down
15 changes: 15 additions & 0 deletions x-pack/platform/plugins/shared/actions/public/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,20 @@ describe('Actions Plugin', () => {
]
`);
});

it('returns isWebhookSslWithPfxEnabled if set in kibana config', async () => {
const context = coreMock.createPluginInitializerContext({
webhook: {
ssl: {
pfx: {
enabled: false,
},
},
},
});
const plugin = new Plugin(context);
const pluginSetup = plugin.setup();
expect(pluginSetup.isWebhookSslWithPfxEnabled).toBe(false);
});
});
});
11 changes: 11 additions & 0 deletions x-pack/platform/plugins/shared/actions/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,37 @@ export interface ActionsPublicPluginSetup {
emails: string[],
options?: ValidateEmailAddressesOptions
): ValidatedEmail[];
isWebhookSslWithPfxEnabled?: boolean;
}

export interface Config {
email: {
domain_allowlist: string[];
};
webhook: {
ssl: {
pfx: {
enabled: boolean;
};
};
};
}

export class Plugin implements CorePlugin<ActionsPublicPluginSetup> {
private readonly allowedEmailDomains: string[] | null = null;
private readonly webhookSslWithPfxEnabled: boolean;

constructor(ctx: PluginInitializerContext<Config>) {
const config = ctx.config.get();
this.allowedEmailDomains = config.email?.domain_allowlist || null;
this.webhookSslWithPfxEnabled = config.webhook?.ssl.pfx.enabled ?? true;
}

public setup(): ActionsPublicPluginSetup {
return {
validateEmailAddresses: (emails: string[], options: ValidateEmailAddressesOptions) =>
validateEmails(this.allowedEmailDomains, emails, options),
isWebhookSslWithPfxEnabled: this.webhookSslWithPfxEnabled,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ const createActionsConfigMock = () => {
getMaxAttempts: jest.fn().mockReturnValue(3),
enableFooterInEmail: jest.fn().mockReturnValue(true),
getMaxQueued: jest.fn().mockReturnValue(1000),
getWebhookSettings: jest.fn().mockReturnValue({
ssl: {
pfx: {
enabled: true,
},
},
}),
getAwsSesConfig: jest.fn().mockReturnValue(null),
};
return mocked;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,56 @@ describe('getMaxQueued()', () => {
});
});

describe('getWebhookSettings()', () => {
test('returns the webhook settings from config', () => {
const config: ActionsConfig = {
...defaultActionsConfig,
webhook: {
ssl: {
pfx: {
enabled: true,
},
},
},
};
const webhookSettings = getActionsConfigurationUtilities(config).getWebhookSettings();
expect(webhookSettings).toEqual({
ssl: {
pfx: {
enabled: true,
},
},
});
});

test('returns the webhook settings from config when pfx is false', () => {
const config: ActionsConfig = {
...defaultActionsConfig,
webhook: {
ssl: {
pfx: {
enabled: false,
},
},
},
};
const webhookSettings = getActionsConfigurationUtilities(config).getWebhookSettings();
expect(webhookSettings).toEqual({
ssl: {
pfx: {
enabled: false,
},
},
});
});

test('returns true when no webhook settings are defined', () => {
const config: ActionsConfig = defaultActionsConfig;
const webhookSettings = getActionsConfigurationUtilities(config).getWebhookSettings();
expect(webhookSettings).toEqual({ ssl: { pfx: { enabled: true } } });
});
});

describe('getAwsSesConfig()', () => {
test('returns null when no email config set', () => {
const acu = getActionsConfigurationUtilities(defaultActionsConfig);
Expand Down
16 changes: 16 additions & 0 deletions x-pack/platform/plugins/shared/actions/server/actions_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ export interface ActionsConfigurationUtilities {
): string | undefined;
enableFooterInEmail: () => boolean;
getMaxQueued: () => number;
getWebhookSettings(): {
ssl: {
pfx: {
enabled: boolean;
};
};
};
getAwsSesConfig: () => AwsSesConfig;
}

Expand Down Expand Up @@ -226,6 +233,15 @@ export function getActionsConfigurationUtilities(
},
enableFooterInEmail: () => config.enableFooterInEmail,
getMaxQueued: () => config.queued?.max || DEFAULT_QUEUED_MAX,
getWebhookSettings: () => {
return {
ssl: {
pfx: {
enabled: config.webhook?.ssl.pfx.enabled ?? true,
},
},
};
},
getAwsSesConfig: () => {
if (config.email?.services?.ses.host && config.email?.services?.ses.port) {
return {
Expand Down
26 changes: 26 additions & 0 deletions x-pack/platform/plugins/shared/actions/server/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,32 @@ describe('config validation', () => {
expect(result.email?.domain_allowlist).toEqual(['a.com', 'b.c.com', 'd.e.f.com']);
});

test('validates xpack.actions.webhook', () => {
const config: Record<string, unknown> = {};
let result = configSchema.validate(config);
expect(result.webhook === undefined);

config.webhook = {};
result = configSchema.validate(config);
expect(result.webhook?.ssl.pfx.enabled).toEqual(true);

config.webhook = { ssl: {} };
result = configSchema.validate(config);
expect(result.webhook?.ssl.pfx.enabled).toEqual(true);

config.webhook = { ssl: { pfx: {} } };
result = configSchema.validate(config);
expect(result.webhook?.ssl.pfx.enabled).toEqual(true);

config.webhook = { ssl: { pfx: { enabled: false } } };
result = configSchema.validate(config);
expect(result.webhook?.ssl.pfx.enabled).toEqual(false);

config.webhook = { ssl: { pfx: { enabled: true } } };
result = configSchema.validate(config);
expect(result.webhook?.ssl.pfx.enabled).toEqual(true);
});

describe('email.services.ses', () => {
const config: Record<string, unknown> = {};
test('validates no email config at all', () => {
Expand Down
9 changes: 9 additions & 0 deletions x-pack/platform/plugins/shared/actions/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ export const configSchema = schema.object({
})
),
}),
webhook: schema.maybe(
schema.object({
ssl: schema.object({
pfx: schema.object({
enabled: schema.boolean({ defaultValue: true }),
}),
}),
})
),
});

export type ActionsConfig = TypeOf<typeof configSchema>;
Expand Down
1 change: 1 addition & 0 deletions x-pack/platform/plugins/shared/actions/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const config: PluginConfigDescriptor<ActionsConfig> = {
schema: configSchema,
exposeToBrowser: {
email: { domain_allowlist: true },
webhook: { ssl: { pfx: { enabled: true } } },
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ import * as i18n from './translations';

interface Props {
readOnly: boolean;
isPfxEnabled?: boolean;
}

const { emptyField } = fieldValidators;

const VERIFICATION_MODE_DEFAULT = 'full';

export const AuthConfig: FunctionComponent<Props> = ({ readOnly }) => {
export const AuthConfig: FunctionComponent<Props> = ({ readOnly, isPfxEnabled = true }) => {
const { setFieldValue, getFieldDefaultValue } = useFormContext();
const [{ config, __internal__ }] = useFormData({
watch: [
Expand Down Expand Up @@ -112,6 +113,7 @@ export const AuthConfig: FunctionComponent<Props> = ({ readOnly }) => {
readOnly={readOnly}
certTypeDefaultValue={certTypeDefaultValue}
certType={certType}
isPfxEnabled={isPfxEnabled}
/>
),
'data-test-subj': 'authSSL',
Expand Down Expand Up @@ -180,7 +182,7 @@ export const AuthConfig: FunctionComponent<Props> = ({ readOnly }) => {
onClick={() => removeItem(item.id)}
iconType="minusInCircle"
aria-label={i18n.DELETE_BUTTON}
style={{ marginTop: '28px' }}
css={{ marginTop: '28px' }}
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,26 @@ import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SSLCertType } from '../../../common/auth/constants';
import { AuthFormTestProvider } from '../../connector_types/lib/test_utils';
import { useConnectorContext } from '@kbn/triggers-actions-ui-plugin/public';
import * as i18n from './translations';

const certTypeDefaultValue: SSLCertType = SSLCertType.CRT;

jest.mock('@kbn/triggers-actions-ui-plugin/public', () => ({
useConnectorContext: jest.fn(),
}));

describe('SSLCertFields', () => {
beforeEach(() => {
(useConnectorContext as jest.Mock).mockReturnValue({
services: { isWebhookSslWithPfxEnabled: true },
});
});

afterEach(() => {
jest.clearAllMocks();
});

const onSubmit = jest.fn();

it('renders all fields for certType=CRT', async () => {
Expand Down Expand Up @@ -221,3 +237,33 @@ describe('SSLCertFields', () => {
});
});
});

describe('validation with PFX disabled', () => {
beforeEach(() => {
(useConnectorContext as jest.Mock).mockReturnValue({
services: { isWebhookSslWithPfxEnabled: false },
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('does not render PFX tab when PFX is disabled', async () => {
render(
<AuthFormTestProvider onSubmit={jest.fn()}>
<SSLCertFields
readOnly={false}
certTypeDefaultValue={certTypeDefaultValue}
certType={SSLCertType.CRT}
isPfxEnabled={false}
/>
</AuthFormTestProvider>
);

expect(await screen.findByTestId('sslCertFields')).toBeInTheDocument();
expect(await screen.findByTestId('webhookSSLPassphraseInput')).toBeInTheDocument();
expect(await screen.findByTestId('webhookCertTypeTabs')).toBeInTheDocument();
expect(screen.queryByText(i18n.CERT_TYPE_PFX)).not.toBeInTheDocument();
});
});
Loading
Loading