mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Alerting: Update Discord settings to treat 'url' as a secure setting (#69588)
* make discord url secure * support migrating unsecure settings to secure settings * Update public/app/features/alerting/unified/utils/receiver-form.ts Co-authored-by: William Wernert <william.wernert@grafana.com> --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> Co-authored-by: William Wernert <william.wernert@grafana.com>
This commit is contained in:
@@ -997,6 +997,7 @@ func GetAvailableNotifiers() []*NotifierPlugin {
|
||||
Placeholder: "Discord webhook URL",
|
||||
PropertyName: "url",
|
||||
Required: true,
|
||||
Secure: true,
|
||||
},
|
||||
{
|
||||
Label: "Avatar URL",
|
||||
|
||||
@@ -68,6 +68,7 @@ export function ChannelOptions<R extends ChannelValues>({
|
||||
)?.[option.propertyName];
|
||||
|
||||
const defaultValue = defaultValues?.settings?.[option.propertyName];
|
||||
const hasSecureProperty = defaultValues.secureSettings?.[option.propertyName];
|
||||
|
||||
return (
|
||||
<OptionField
|
||||
@@ -76,7 +77,7 @@ export function ChannelOptions<R extends ChannelValues>({
|
||||
key={key}
|
||||
error={error}
|
||||
pathPrefix={pathPrefix}
|
||||
pathSuffix={option.secure ? 'secureSettings.' : 'settings.'}
|
||||
pathSuffix={option.secure && hasSecureProperty ? 'secureSettings.' : 'settings.'}
|
||||
option={option}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -68,7 +68,9 @@ export const GrafanaReceiverForm = ({ existing, alertManagerSourceName, config }
|
||||
}, [existing, grafanaNotifiers.result]);
|
||||
|
||||
const onSubmit = (values: ReceiverFormValues<GrafanaChannelValues>) => {
|
||||
const newReceiver = formValuesToGrafanaReceiver(values, id2original, defaultChannelValues);
|
||||
const notifiers = grafanaNotifiers.result;
|
||||
|
||||
const newReceiver = formValuesToGrafanaReceiver(values, id2original, defaultChannelValues, notifiers ?? []);
|
||||
dispatch(
|
||||
updateAlertManagerConfigAction({
|
||||
newConfig: updateConfigWithReceiver(config, newReceiver, existing?.name),
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`formValuesToGrafanaReceiver should migrate regular settings to secure settings if the field is defined as secure 1`] = `
|
||||
{
|
||||
"grafana_managed_receiver_configs": [
|
||||
{
|
||||
"disableResolveMessage": false,
|
||||
"name": "my-receiver",
|
||||
"secureSettings": {
|
||||
"url": "https://foo.bar/",
|
||||
},
|
||||
"settings": {},
|
||||
"type": "discord",
|
||||
"uid": "abc123",
|
||||
},
|
||||
],
|
||||
"name": "my-receiver",
|
||||
}
|
||||
`;
|
||||
@@ -1,4 +1,8 @@
|
||||
import { omitEmptyValues, omitEmptyUnlessExisting } from './receiver-form';
|
||||
import { NotifierDTO } from 'app/types';
|
||||
|
||||
import { GrafanaChannelValues, ReceiverFormValues } from '../types/receiver-form';
|
||||
|
||||
import { formValuesToGrafanaReceiver, omitEmptyValues, omitEmptyUnlessExisting } from './receiver-form';
|
||||
|
||||
describe('Receiver form utils', () => {
|
||||
describe('omitEmptyStringValues', () => {
|
||||
@@ -64,3 +68,46 @@ describe('Receiver form utils', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('formValuesToGrafanaReceiver', () => {
|
||||
it('should migrate regular settings to secure settings if the field is defined as secure', () => {
|
||||
const formValues: ReceiverFormValues<GrafanaChannelValues> = {
|
||||
name: 'my-receiver',
|
||||
items: [
|
||||
{
|
||||
__id: '1',
|
||||
secureSettings: {},
|
||||
secureFields: {},
|
||||
type: 'discord',
|
||||
settings: {
|
||||
url: 'https://foo.bar/',
|
||||
},
|
||||
disableResolveMessage: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const channelMap = {
|
||||
'1': {
|
||||
uid: 'abc123',
|
||||
secureSettings: {},
|
||||
secureFields: {},
|
||||
type: 'discord',
|
||||
settings: {
|
||||
url: 'https://foo.bar/',
|
||||
},
|
||||
disableResolveMessage: false,
|
||||
},
|
||||
};
|
||||
|
||||
const notifiers = [
|
||||
{
|
||||
type: 'discord',
|
||||
options: [{ propertyName: 'url', secure: true }],
|
||||
},
|
||||
] as NotifierDTO[];
|
||||
|
||||
// @ts-expect-error
|
||||
expect(formValuesToGrafanaReceiver(formValues, channelMap, {}, notifiers)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isArray, isNil, omitBy } from 'lodash';
|
||||
import { isArray, omit, pick, isNil, omitBy } from 'lodash';
|
||||
|
||||
import {
|
||||
AlertManagerCortexConfig,
|
||||
@@ -79,13 +79,22 @@ export function cloudReceiverToFormValues(
|
||||
export function formValuesToGrafanaReceiver(
|
||||
values: ReceiverFormValues<GrafanaChannelValues>,
|
||||
channelMap: GrafanaChannelMap,
|
||||
defaultChannelValues: GrafanaChannelValues
|
||||
defaultChannelValues: GrafanaChannelValues,
|
||||
notifiers: NotifierDTO[]
|
||||
): Receiver {
|
||||
return {
|
||||
name: values.name,
|
||||
grafana_managed_receiver_configs: (values.items ?? []).map((channelValues) => {
|
||||
const existing: GrafanaManagedReceiverConfig | undefined = channelMap[channelValues.__id];
|
||||
return formChannelValuesToGrafanaChannelConfig(channelValues, defaultChannelValues, values.name, existing);
|
||||
const notifier = notifiers.find((notifier) => notifier.type === channelValues.type);
|
||||
|
||||
return formChannelValuesToGrafanaChannelConfig(
|
||||
channelValues,
|
||||
defaultChannelValues,
|
||||
values.name,
|
||||
existing,
|
||||
notifier
|
||||
);
|
||||
}),
|
||||
};
|
||||
}
|
||||
@@ -202,7 +211,7 @@ function grafanaChannelConfigToFormChannelValues(
|
||||
|
||||
// work around https://github.com/grafana/alerting-squad/issues/100
|
||||
notifier?.options.forEach((option) => {
|
||||
if (option.secure && values.settings[option.propertyName]) {
|
||||
if (option.secure && values.secureSettings[option.propertyName]) {
|
||||
delete values.settings[option.propertyName];
|
||||
values.secureFields[option.propertyName] = true;
|
||||
}
|
||||
@@ -215,7 +224,8 @@ export function formChannelValuesToGrafanaChannelConfig(
|
||||
values: GrafanaChannelValues,
|
||||
defaults: GrafanaChannelValues,
|
||||
name: string,
|
||||
existing?: GrafanaManagedReceiverConfig
|
||||
existing?: GrafanaManagedReceiverConfig,
|
||||
notifier?: NotifierDTO
|
||||
): GrafanaManagedReceiverConfig {
|
||||
const channel: GrafanaManagedReceiverConfig = {
|
||||
settings: omitEmptyValues({
|
||||
@@ -228,9 +238,25 @@ export function formChannelValuesToGrafanaChannelConfig(
|
||||
disableResolveMessage:
|
||||
values.disableResolveMessage ?? existing?.disableResolveMessage ?? defaults.disableResolveMessage,
|
||||
};
|
||||
|
||||
// find all secure field definitions
|
||||
const secureFieldNames: string[] =
|
||||
notifier?.options.filter((option) => option.secure).map((option) => option.propertyName) ?? [];
|
||||
|
||||
// we make sure all fields that are marked as "secure" will be moved to "SecureSettings" instead of "settings"
|
||||
const shouldBeSecure = pick(channel.settings, secureFieldNames);
|
||||
channel.secureSettings = {
|
||||
...shouldBeSecure,
|
||||
...channel.secureSettings,
|
||||
};
|
||||
|
||||
// remove the secure ones from the regular settings
|
||||
channel.settings = omit(channel.settings, secureFieldNames);
|
||||
|
||||
if (existing) {
|
||||
channel.uid = existing.uid;
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user