-
Notifications
You must be signed in to change notification settings - Fork 8.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Uptime] Update TLS settings #64111
[Uptime] Update TLS settings #64111
Changes from 2 commits
674857e
7d2bf4c
caf3ef2
d0246a7
f7678b6
0ddd97b
ef21286
8412951
59e60e8
d47d429
a1fdf46
a6b014b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { DynamicSettings } from '../runtime_types'; | ||
|
||
export const DYNAMIC_SETTINGS_DEFAULTS: DynamicSettings = { | ||
heartbeatIndices: 'heartbeat-8*', | ||
certificatesThresholds: { | ||
expiration: 7, | ||
age: 365, | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,9 +6,9 @@ | |
|
||
import * as t from 'io-ts'; | ||
|
||
export const CertificatesStatesThresholdType = t.interface({ | ||
warningState: t.number, | ||
errorState: t.number, | ||
export const CertificatesStatesThresholdType = t.partial({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this shouldn't be partial. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would it make sense just to rename it CertStateThresholds WDYT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done! |
||
age: t.number, | ||
expiration: t.number, | ||
}); | ||
|
||
export const DynamicSettingsType = t.intersection([ | ||
|
@@ -32,11 +32,3 @@ export const DynamicSettingsSaveType = t.intersection([ | |
export type DynamicSettings = t.TypeOf<typeof DynamicSettingsType>; | ||
export type DynamicSettingsSaveResponse = t.TypeOf<typeof DynamicSettingsSaveType>; | ||
export type CertificatesStatesThreshold = t.TypeOf<typeof CertificatesStatesThresholdType>; | ||
|
||
export const defaultDynamicSettings: DynamicSettings = { | ||
heartbeatIndices: 'heartbeat-8*', | ||
certificatesThresholds: { | ||
errorState: 7, | ||
warningState: 30, | ||
}, | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,18 +12,16 @@ import { | |
EuiFormRow, | ||
EuiCode, | ||
EuiFieldNumber, | ||
EuiText, | ||
EuiTitle, | ||
EuiSpacer, | ||
EuiSelect, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
} from '@elastic/eui'; | ||
import { defaultDynamicSettings, DynamicSettings } from '../../../common/runtime_types'; | ||
import { DynamicSettings } from '../../../common/runtime_types'; | ||
import { selectDynamicSettings } from '../../state/selectors'; | ||
|
||
type NumStr = string | number; | ||
|
||
export type OnFieldChangeType = (field: string, value?: NumStr) => void; | ||
export type OnFieldChangeType = (changedValues: Partial<DynamicSettings>) => void; | ||
|
||
export interface SettingsFormProps { | ||
onChange: OnFieldChangeType; | ||
|
@@ -55,15 +53,15 @@ export const CertificateExpirationForm: React.FC<SettingsFormProps> = ({ | |
title={ | ||
<h4> | ||
<FormattedMessage | ||
id="xpack.uptime.sourceConfiguration.stateThresholds" | ||
defaultMessage="Expiration State Thresholds" | ||
id="xpack.uptime.sourceConfiguration.expirationThreshold" | ||
defaultMessage="Expiration/Age Thresholds" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should also add that text here which got updated in ACs "Change the threshold for displaying and alerting on certificate errors. Note, this will affect any configured alerts" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
/> | ||
</h4> | ||
} | ||
description={ | ||
<FormattedMessage | ||
id="xpack.uptime.sourceConfiguration.stateThresholdsDescription" | ||
defaultMessage="Set certificate expiration warning/error thresholds" | ||
id="xpack.uptime.sourceConfiguration.certificateThresholdDescription" | ||
defaultMessage="Set certificate expiration/age thresholds" | ||
/> | ||
} | ||
> | ||
|
@@ -76,38 +74,42 @@ export const CertificateExpirationForm: React.FC<SettingsFormProps> = ({ | |
id="xpack.uptime.sourceConfiguration.errorStateDefaultValue" | ||
defaultMessage="The default value is {defaultValue}" | ||
values={{ | ||
defaultValue: ( | ||
<EuiCode>{defaultDynamicSettings?.certificatesThresholds?.errorState}</EuiCode> | ||
), | ||
defaultValue: <EuiCode>{dss.settings.certificatesThresholds?.expiration}</EuiCode>, | ||
}} | ||
/> | ||
} | ||
isInvalid={!!fieldErrors?.certificatesThresholds?.errorState} | ||
label={ | ||
<FormattedMessage | ||
id="xpack.uptime.sourceConfiguration.errorStateLabel" | ||
defaultMessage="Error state" | ||
defaultMessage="Expiration threshold" | ||
/> | ||
} | ||
> | ||
<EuiFlexGroup> | ||
<EuiFlexItem grow={2}> | ||
<EuiFieldNumber | ||
data-test-subj={`error-state-threshold-input-${dss.loading ? 'loading' : 'loaded'}`} | ||
data-test-subj={`expiration-threshold-input-${dss.loading ? 'loading' : 'loaded'}`} | ||
fullWidth | ||
disabled={isDisabled} | ||
isLoading={dss.loading} | ||
value={formFields?.certificatesThresholds?.errorState || ''} | ||
value={formFields?.certificatesThresholds?.expiration || ''} | ||
onChange={({ currentTarget: { value } }: any) => | ||
onChange( | ||
'certificatesThresholds.errorState', | ||
value === '' ? undefined : Number(value) | ||
) | ||
onChange({ | ||
certificatesThresholds: { | ||
expiration: Number(value), | ||
}, | ||
}) | ||
} | ||
/> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={1}> | ||
<EuiSelect options={[{ value: 'day', text: 'Days' }]} /> | ||
<EuiText> | ||
<FormattedMessage | ||
id="xpack.uptime.sourceConfiguration.ageLimit.units.days" | ||
defaultMessage="Days" | ||
/> | ||
</EuiText> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiFormRow> | ||
|
@@ -120,37 +122,40 @@ export const CertificateExpirationForm: React.FC<SettingsFormProps> = ({ | |
id="xpack.uptime.sourceConfiguration.warningStateDefaultValue" | ||
defaultMessage="The default value is {defaultValue}" | ||
values={{ | ||
defaultValue: ( | ||
<EuiCode>{defaultDynamicSettings?.certificatesThresholds?.warningState}</EuiCode> | ||
), | ||
defaultValue: <EuiCode>{dss.settings.certificatesThresholds?.age}</EuiCode>, | ||
}} | ||
/> | ||
} | ||
isInvalid={!!fieldErrors?.certificatesThresholds?.warningState} | ||
label={ | ||
<FormattedMessage | ||
id="xpack.uptime.sourceConfiguration.warningStateLabel" | ||
defaultMessage="Warning state" | ||
defaultMessage="Age limit" | ||
/> | ||
} | ||
> | ||
<EuiFlexGroup> | ||
<EuiFlexItem grow={2}> | ||
<EuiFieldNumber | ||
data-test-subj={`warning-state-threshold-input-${ | ||
dss.loading ? 'loading' : 'loaded' | ||
}`} | ||
data-test-subj={`age-threshold-input-${dss.loading ? 'loading' : 'loaded'}`} | ||
fullWidth | ||
disabled={isDisabled} | ||
isLoading={dss.loading} | ||
value={formFields?.certificatesThresholds?.warningState || ''} | ||
value={formFields?.certificatesThresholds?.age || ''} | ||
onChange={(event: any) => | ||
onChange('certificatesThresholds.warningState', Number(event.currentTarget.value)) | ||
onChange({ | ||
certificatesThresholds: { age: Number(event.currentTarget.value) }, | ||
}) | ||
} | ||
/> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={1}> | ||
<EuiSelect options={[{ value: 'day', text: 'Days' }]} /> | ||
<EuiText> | ||
<FormattedMessage | ||
id="xpack.uptime.sourceConfiguration.ageLimit.units.days" | ||
defaultMessage="Days" | ||
/> | ||
</EuiText> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiFormRow> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,6 @@ import { | |
EuiTitle, | ||
EuiSpacer, | ||
} from '@elastic/eui'; | ||
import { defaultDynamicSettings } from '../../../common/runtime_types'; | ||
import { selectDynamicSettings } from '../../state/selectors'; | ||
import { SettingsFormProps } from './certificate_form'; | ||
|
||
|
@@ -63,7 +62,7 @@ export const IndicesForm: React.FC<SettingsFormProps> = ({ | |
id="xpack.uptime.sourceConfiguration.heartbeatIndicesDefaultValue" | ||
defaultMessage="The default value is {defaultValue}" | ||
values={{ | ||
defaultValue: <EuiCode>{defaultDynamicSettings.heartbeatIndices}</EuiCode>, | ||
defaultValue: <EuiCode>{dss.settings.heartbeatIndices}</EuiCode>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change will display the current value? default value should come from constant? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right you are, we don't want that to change! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is using defaults again now. |
||
}} | ||
/> | ||
} | ||
|
@@ -81,7 +80,7 @@ export const IndicesForm: React.FC<SettingsFormProps> = ({ | |
disabled={isDisabled} | ||
isLoading={dss.loading} | ||
value={formFields?.heartbeatIndices || ''} | ||
onChange={(event: any) => onChange('heartbeatIndices', event.currentTarget.value)} | ||
onChange={(event: any) => onChange({ heartbeatIndices: event.currentTarget.value })} | ||
/> | ||
</EuiFormRow> | ||
</EuiDescribedFormGroup> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,8 +17,7 @@ import { | |
} from '@elastic/eui'; | ||
import { FormattedMessage } from '@kbn/i18n/react'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { cloneDeep, isEqual, set } from 'lodash'; | ||
import { i18n } from '@kbn/i18n'; | ||
import { isEqual, merge } from 'lodash'; | ||
import { Link } from 'react-router-dom'; | ||
import { selectDynamicSettings } from '../state/selectors'; | ||
import { getDynamicSettings, setDynamicSettings } from '../state/actions/dynamic_settings'; | ||
|
@@ -32,14 +31,15 @@ import { | |
CertificateExpirationForm, | ||
OnFieldChangeType, | ||
} from '../components/settings/certificate_form'; | ||
import * as Translations from './translations'; | ||
|
||
const getFieldErrors = (formFields: DynamicSettings | null) => { | ||
if (formFields) { | ||
const blankStr = 'May not be blank'; | ||
const { certificatesThresholds, heartbeatIndices } = formFields; | ||
const heartbeatIndErr = heartbeatIndices.match(/^\S+$/) ? '' : blankStr; | ||
const errorStateErr = certificatesThresholds?.errorState ? null : blankStr; | ||
const warningStateErr = certificatesThresholds?.warningState ? null : blankStr; | ||
const errorStateErr = certificatesThresholds?.expiration ? null : blankStr; | ||
const warningStateErr = certificatesThresholds?.age ? null : blankStr; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you also rename var name? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I realized we needed to improve this, so I added a type and renamed the var usage in 59e60e8. |
||
return { | ||
heartbeatIndices: heartbeatIndErr, | ||
certificatesThresholds: | ||
|
@@ -57,10 +57,7 @@ const getFieldErrors = (formFields: DynamicSettings | null) => { | |
export const SettingsPage = () => { | ||
const dss = useSelector(selectDynamicSettings); | ||
|
||
const settingsBreadcrumbText = i18n.translate('xpack.uptime.settingsBreadcrumbText', { | ||
defaultMessage: 'Settings', | ||
}); | ||
useBreadcrumbs([{ text: settingsBreadcrumbText }]); | ||
useBreadcrumbs([{ text: Translations.settings.breadcrumbText }]); | ||
|
||
useUptimeTelemetry(UptimePage.Settings); | ||
|
||
|
@@ -70,52 +67,32 @@ export const SettingsPage = () => { | |
dispatch(getDynamicSettings()); | ||
}, [dispatch]); | ||
|
||
const [formFields, setFormFields] = useState<DynamicSettings | null>(dss.settings || null); | ||
|
||
if (!dss.loadError && formFields == null && dss.settings) { | ||
setFormFields({ ...dss.settings }); | ||
} | ||
const [formFields, setFormFields] = useState<DynamicSettings>({ ...dss.settings }); | ||
|
||
const fieldErrors = getFieldErrors(formFields); | ||
|
||
const isFormValid = !(fieldErrors && Object.values(fieldErrors).find(v => !!v)); | ||
|
||
const onChangeFormField: OnFieldChangeType = (field, value) => { | ||
if (formFields) { | ||
const newFormFields = cloneDeep(formFields); | ||
set(newFormFields, field, value); | ||
setFormFields(cloneDeep(newFormFields)); | ||
} | ||
}; | ||
const onChangeFormField: OnFieldChangeType = changedField => | ||
setFormFields(Object.assign({ ...merge(formFields, changedField) })); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We are using merge bcoz Object.assign doesn't take of nested merging, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've gotten rid of merge altogether because it isn't pure and it was editing the state var. I'm wondering if settings shouldn't just be a flat object to avoid recursive concerns when editing slices of it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes i think having a right data structure is important, i do agree, having nested have made a lot of complexity. if you think, it's worth an effort, go ahead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll make a follow-up issue. We have other more important stuff we need to review and it's not worth holding that up for more work in this patch. We don't have any further settings changes planned for the time being, so this complexity shouldn't increase any more than what it is right now until we can get to it. It should be a light patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Issue: elastic/uptime#175 |
||
|
||
const onApply = (event: React.FormEvent) => { | ||
event.preventDefault(); | ||
if (formFields) { | ||
dispatch(setDynamicSettings(formFields)); | ||
} | ||
dispatch(setDynamicSettings(formFields)); | ||
}; | ||
|
||
const resetForm = () => { | ||
if (formFields && dss.settings) { | ||
setFormFields({ ...dss.settings }); | ||
} | ||
}; | ||
const resetForm = () => setFormFields({ ...dss.settings }); | ||
|
||
const isFormDirty = dss.settings ? !isEqual(dss.settings, formFields) : true; | ||
const isFormDirty = !isEqual(dss.settings, formFields); | ||
const canEdit: boolean = | ||
!!useKibana().services?.application?.capabilities.uptime.configureSettings || false; | ||
const isFormDisabled = dss.loading || !canEdit; | ||
|
||
const editNoticeTitle = i18n.translate('xpack.uptime.settings.cannotEditTitle', { | ||
defaultMessage: 'You do not have permission to edit settings.', | ||
}); | ||
const editNoticeText = i18n.translate('xpack.uptime.settings.cannotEditText', { | ||
defaultMessage: | ||
"Your user currently has 'Read' permissions for the Uptime app. Enable a permissions-level of 'All' to edit these settings.", | ||
}); | ||
const cannotEditNotice = canEdit ? null : ( | ||
<> | ||
<EuiCallOut title={editNoticeTitle}>{editNoticeText}</EuiCallOut> | ||
<EuiCallOut title={Translations.settings.editNoticeTitle}> | ||
{Translations.settings.editNoticeText} | ||
</EuiCallOut> | ||
<EuiSpacer size="s" /> | ||
</> | ||
); | ||
|
@@ -124,9 +101,7 @@ export const SettingsPage = () => { | |
<> | ||
<Link to={OVERVIEW_ROUTE} data-test-subj="uptimeSettingsToOverviewLink"> | ||
<EuiButtonEmpty size="s" color="primary" iconType="arrowLeft"> | ||
{i18n.translate('xpack.uptime.settings.returnToOverviewLinkLabel', { | ||
defaultMessage: 'Return to overview', | ||
})} | ||
{Translations.settings.returnToOverviewLinkLabel} | ||
</EuiButtonEmpty> | ||
</Link> | ||
<EuiSpacer size="s" /> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { i18n } from '@kbn/i18n'; | ||
|
||
export const settings = { | ||
breadcrumbText: i18n.translate('xpack.uptime.settingsBreadcrumbText', { | ||
defaultMessage: 'Settings', | ||
}), | ||
editNoticeTitle: i18n.translate('xpack.uptime.settings.cannotEditTitle', { | ||
defaultMessage: 'You do not have permission to edit settings.', | ||
}), | ||
editNoticeText: i18n.translate('xpack.uptime.settings.cannotEditText', { | ||
defaultMessage: | ||
"Your user currently has 'Read' permissions for the Uptime app. Enable a permissions-level of 'All' to edit these settings.", | ||
}), | ||
returnToOverviewLinkLabel: i18n.translate('xpack.uptime.settings.returnToOverviewLinkLabel', { | ||
defaultMessage: 'Return to overview', | ||
}), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this should be 30 days be default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in d0246a7.