* refactoring apm integration sections * adding agent auth section * refactoring * adding some unit tests * fixing ts issue * removing unnecessary section * hide fields * removing suggestions when combo * fixing apm migration * addressing PR comments * addressing PR changes Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Cauê Marcondes <55978943+cauemarcondes@users.noreply.github.com>
This commit is contained in:
parent
f274289504
commit
18b31701e3
|
@ -21,7 +21,7 @@ export function CreateAPMPolicyForm({ newPolicy, onChange }: Props) {
|
|||
const [firstInput, ...restInputs] = newPolicy?.inputs;
|
||||
const vars = firstInput?.vars;
|
||||
|
||||
function handleChange(newVars: PackagePolicyVars, isValid: boolean) {
|
||||
function updateAPMPolicy(newVars: PackagePolicyVars, isValid: boolean) {
|
||||
onChange({
|
||||
isValid,
|
||||
updatedPolicy: {
|
||||
|
@ -31,6 +31,10 @@ export function CreateAPMPolicyForm({ newPolicy, onChange }: Props) {
|
|||
});
|
||||
}
|
||||
return (
|
||||
<APMPolicyForm vars={vars} onChange={handleChange} isCloudPolicy={false} />
|
||||
<APMPolicyForm
|
||||
vars={vars}
|
||||
updateAPMPolicy={updateAPMPolicy}
|
||||
isCloudPolicy={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ export function EditAPMPolicyForm({ newPolicy, onChange }: Props) {
|
|||
const [firstInput, ...restInputs] = newPolicy?.inputs;
|
||||
const vars = firstInput?.vars;
|
||||
|
||||
function handleChange(newVars: PackagePolicyVars, isValid: boolean) {
|
||||
function updateAPMPolicy(newVars: PackagePolicyVars, isValid: boolean) {
|
||||
onChange({
|
||||
isValid,
|
||||
updatedPolicy: {
|
||||
|
@ -35,7 +35,7 @@ export function EditAPMPolicyForm({ newPolicy, onChange }: Props) {
|
|||
return (
|
||||
<APMPolicyForm
|
||||
vars={vars}
|
||||
onChange={handleChange}
|
||||
updateAPMPolicy={updateAPMPolicy}
|
||||
isCloudPolicy={newPolicy.policy_id === POLICY_ELASTIC_AGENT_ON_CLOUD}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -5,30 +5,124 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { OnFormChangeFn, PackagePolicyVars } from './typings';
|
||||
import { APMSettingsForm } from './settings/apm_settings';
|
||||
import { RUMSettingsForm } from './settings/rum_settings';
|
||||
import { TLSSettingsForm } from './settings/tls_settings';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useMemo } from 'react';
|
||||
import { getAgentAuthorizationSettings } from './settings_definition/agent_authorization_settings';
|
||||
import { getApmSettings } from './settings_definition/apm_settings';
|
||||
import {
|
||||
getRUMSettings,
|
||||
isRUMFormValid,
|
||||
} from './settings_definition/rum_settings';
|
||||
import {
|
||||
getTLSSettings,
|
||||
isTLSFormValid,
|
||||
} from './settings_definition/tls_settings';
|
||||
import { SettingsForm, SettingsSection } from './settings_form';
|
||||
import { isSettingsFormValid, mergeNewVars } from './settings_form/utils';
|
||||
import { PackagePolicyVars } from './typings';
|
||||
|
||||
interface Props {
|
||||
onChange: OnFormChangeFn;
|
||||
updateAPMPolicy: (newVars: PackagePolicyVars, isValid: boolean) => void;
|
||||
vars?: PackagePolicyVars;
|
||||
isCloudPolicy: boolean;
|
||||
}
|
||||
|
||||
export function APMPolicyForm({ vars = {}, isCloudPolicy, onChange }: Props) {
|
||||
export function APMPolicyForm({
|
||||
vars = {},
|
||||
isCloudPolicy,
|
||||
updateAPMPolicy,
|
||||
}: Props) {
|
||||
const {
|
||||
apmSettings,
|
||||
rumSettings,
|
||||
tlsSettings,
|
||||
agentAuthorizationSettings,
|
||||
} = useMemo(() => {
|
||||
return {
|
||||
apmSettings: getApmSettings({ isCloudPolicy }),
|
||||
rumSettings: getRUMSettings(),
|
||||
tlsSettings: getTLSSettings(),
|
||||
agentAuthorizationSettings: getAgentAuthorizationSettings({
|
||||
isCloudPolicy,
|
||||
}),
|
||||
};
|
||||
}, [isCloudPolicy]);
|
||||
|
||||
function handleFormChange(key: string, value: any) {
|
||||
// Merge new key/value with the rest of fields
|
||||
const newVars = mergeNewVars(vars, key, value);
|
||||
|
||||
// Validate the entire form before sending it to fleet
|
||||
const isFormValid =
|
||||
isSettingsFormValid(apmSettings, newVars) &&
|
||||
isRUMFormValid(newVars, rumSettings) &&
|
||||
isTLSFormValid(newVars, tlsSettings) &&
|
||||
isSettingsFormValid(agentAuthorizationSettings, newVars);
|
||||
|
||||
updateAPMPolicy(newVars, isFormValid);
|
||||
}
|
||||
|
||||
const settingsSections: SettingsSection[] = [
|
||||
{
|
||||
id: 'apm',
|
||||
title: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.settings.title',
|
||||
{ defaultMessage: 'General' }
|
||||
),
|
||||
subtitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.settings.subtitle',
|
||||
{ defaultMessage: 'Settings for the APM integration.' }
|
||||
),
|
||||
settings: apmSettings,
|
||||
},
|
||||
{
|
||||
id: 'rum',
|
||||
title: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.settings.title',
|
||||
{ defaultMessage: 'Real User Monitoring' }
|
||||
),
|
||||
subtitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.settings.subtitle',
|
||||
{ defaultMessage: 'Manage the configuration of the RUM JS agent.' }
|
||||
),
|
||||
settings: rumSettings,
|
||||
},
|
||||
{
|
||||
id: 'tls',
|
||||
title: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.settings.title',
|
||||
{ defaultMessage: 'TLS Settings' }
|
||||
),
|
||||
subtitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.settings.subtitle',
|
||||
{ defaultMessage: 'Settings for TLS certification.' }
|
||||
),
|
||||
settings: tlsSettings,
|
||||
},
|
||||
{
|
||||
id: 'agentAuthorization',
|
||||
title: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.settings.title',
|
||||
{ defaultMessage: 'Agent authorization' }
|
||||
),
|
||||
settings: agentAuthorizationSettings,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<APMSettingsForm
|
||||
vars={vars}
|
||||
onChange={onChange}
|
||||
isCloudPolicy={isCloudPolicy}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<RUMSettingsForm vars={vars} onChange={onChange} />
|
||||
<EuiSpacer />
|
||||
<TLSSettingsForm vars={vars} onChange={onChange} />
|
||||
{settingsSections.map((settingsSection) => {
|
||||
return (
|
||||
<React.Fragment key={settingsSection.id}>
|
||||
<SettingsForm
|
||||
settingsSection={settingsSection}
|
||||
vars={vars}
|
||||
onChange={handleFormChange}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
* 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';
|
||||
import React from 'react';
|
||||
import { getIntegerRt } from '../../../../../common/agent_configuration/runtime_types/integer_rt';
|
||||
import { OnFormChangeFn, PackagePolicyVars } from '../typings';
|
||||
import { SettingsForm } from './settings_form';
|
||||
import { SettingDefinition } from './typings';
|
||||
import { isSettingsFormValid, mergeNewVars, OPTIONAL_LABEL } from './utils';
|
||||
|
||||
const ENABLE_RUM_KEY = 'enable_rum';
|
||||
const rumSettings: SettingDefinition[] = [
|
||||
{
|
||||
key: ENABLE_RUM_KEY,
|
||||
type: 'boolean',
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.enableRumTitle',
|
||||
{ defaultMessage: 'Enable RUM' }
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.enableRumDescription',
|
||||
{ defaultMessage: 'Enable Real User Monitoring (RUM)' }
|
||||
),
|
||||
settings: [
|
||||
{
|
||||
key: 'rum_allow_headers',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderLabel',
|
||||
{ defaultMessage: 'Allowed origin headers' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderHelpText',
|
||||
{
|
||||
defaultMessage: 'Allowed Origin headers to be sent by User Agents.',
|
||||
}
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderTitle',
|
||||
{ defaultMessage: 'Custom headers' }
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderDescription',
|
||||
{ defaultMessage: 'Configure authentication for the agent' }
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'rum_allow_origins',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowOriginsLabel',
|
||||
{ defaultMessage: 'Access-Control-Allow-Headers' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowOriginsHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Supported Access-Control-Allow-Headers in addition to "Content-Type", "Content-Encoding" and "Accept".',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'rum_response_headers',
|
||||
type: 'area',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumResponseHeadersLabel',
|
||||
{ defaultMessage: 'Custom HTTP response headers' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumResponseHeadersHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Added to RUM responses, e.g. for security policy compliance.',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'advanced_settings',
|
||||
settings: [
|
||||
{
|
||||
key: 'rum_event_rate_limit',
|
||||
type: 'integer',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumEventRateLimitLabel',
|
||||
{ defaultMessage: 'Rate limit events per IP' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumEventRateLimitHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Maximum number of events allowed per IP per second.',
|
||||
}
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumEventRateLimitTitle',
|
||||
{ defaultMessage: 'Limits' }
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumEventRateLimitDescription',
|
||||
{ defaultMessage: 'Configure authentication for the agent' }
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
},
|
||||
{
|
||||
key: 'rum_event_rate_lru_size',
|
||||
type: 'integer',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumEventRateLRUSizeLabel',
|
||||
{ defaultMessage: 'Rate limit cache size' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumEventRateLRUSizeHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Number of unique IPs to be cached for the rate limiter.',
|
||||
}
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
},
|
||||
{
|
||||
key: 'rum_library_pattern',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumLibraryPatternLabel',
|
||||
{ defaultMessage: 'Library Frame Pattern' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumLibraryPatternHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
"Identify library frames by matching a stacktrace frame's file_name and abs_path against this regexp.",
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'rum_allow_service_names',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowServiceNamesLabel',
|
||||
{ defaultMessage: 'Allowed service names' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowServiceNamesTitle',
|
||||
{ defaultMessage: 'Allowed service names' }
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowServiceNamesDescription',
|
||||
{ defaultMessage: 'Configure authentication for the agent' }
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
interface Props {
|
||||
vars: PackagePolicyVars;
|
||||
onChange: OnFormChangeFn;
|
||||
}
|
||||
|
||||
export function RUMSettingsForm({ vars, onChange }: Props) {
|
||||
return (
|
||||
<SettingsForm
|
||||
title={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.settings.title',
|
||||
{ defaultMessage: 'Real User Monitoring' }
|
||||
)}
|
||||
subtitle={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.settings.subtitle',
|
||||
{ defaultMessage: 'Manage the configuration of the RUM JS agent.' }
|
||||
)}
|
||||
settings={rumSettings}
|
||||
vars={vars}
|
||||
onChange={(key, value) => {
|
||||
const newVars = mergeNewVars(vars, key, value);
|
||||
onChange(
|
||||
newVars,
|
||||
// only validates RUM when its flag is enabled
|
||||
!newVars[ENABLE_RUM_KEY].value ||
|
||||
isSettingsFormValid(rumSettings, newVars)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* 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';
|
||||
import React from 'react';
|
||||
import { OnFormChangeFn, PackagePolicyVars } from '../typings';
|
||||
import { SettingsForm } from './settings_form';
|
||||
import { SettingDefinition } from './typings';
|
||||
import {
|
||||
isSettingsFormValid,
|
||||
mergeNewVars,
|
||||
OPTIONAL_LABEL,
|
||||
REQUIRED_LABEL,
|
||||
} from './utils';
|
||||
|
||||
const TLS_ENABLED_KEY = 'tls_enabled';
|
||||
const tlsSettings: SettingDefinition[] = [
|
||||
{
|
||||
key: TLS_ENABLED_KEY,
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsEnabledTitle',
|
||||
{ defaultMessage: 'Enable TLS' }
|
||||
),
|
||||
type: 'boolean',
|
||||
settings: [
|
||||
{
|
||||
key: 'tls_certificate',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCertificateLabel',
|
||||
{ defaultMessage: 'File path to server certificate' }
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCertificateTitle',
|
||||
{ defaultMessage: 'TLS certificate' }
|
||||
),
|
||||
labelAppend: REQUIRED_LABEL,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'tls_key',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsKeyLabel',
|
||||
{ defaultMessage: 'File path to server certificate key' }
|
||||
),
|
||||
labelAppend: REQUIRED_LABEL,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'tls_supported_protocols',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsSupportedProtocolsLabel',
|
||||
{ defaultMessage: 'Supported protocol versions' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
},
|
||||
{
|
||||
key: 'tls_cipher_suites',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesLabel',
|
||||
{ defaultMessage: 'Cipher suites for TLS connections' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesHelpText',
|
||||
{ defaultMessage: 'Not configurable for TLS 1.3.' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
},
|
||||
{
|
||||
key: 'tls_curve_types',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCurveTypesLabel',
|
||||
{ defaultMessage: 'Curve types for ECDHE based cipher suites' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
interface Props {
|
||||
vars: PackagePolicyVars;
|
||||
onChange: OnFormChangeFn;
|
||||
}
|
||||
|
||||
export function TLSSettingsForm({ vars, onChange }: Props) {
|
||||
return (
|
||||
<SettingsForm
|
||||
title={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.settings.title',
|
||||
{ defaultMessage: 'TLS Settings' }
|
||||
)}
|
||||
subtitle={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.settings.subtitle',
|
||||
{ defaultMessage: 'Settings for TLS certification.' }
|
||||
)}
|
||||
settings={tlsSettings}
|
||||
vars={vars}
|
||||
onChange={(key, value) => {
|
||||
const newVars = mergeNewVars(vars, key, value);
|
||||
onChange(
|
||||
newVars,
|
||||
// only validates TLS when its flag is enabled
|
||||
!newVars[TLS_ENABLED_KEY].value ||
|
||||
isSettingsFormValid(tlsSettings, newVars)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* 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 * as t from 'io-ts';
|
||||
|
||||
export type SettingValidation = t.Type<any, string, unknown>;
|
||||
|
||||
interface AdvancedSettings {
|
||||
type: 'advanced_settings';
|
||||
settings: SettingDefinition[];
|
||||
}
|
||||
|
||||
export interface Setting {
|
||||
type:
|
||||
| 'text'
|
||||
| 'combo'
|
||||
| 'area'
|
||||
| 'boolean'
|
||||
| 'integer'
|
||||
| 'bytes'
|
||||
| 'duration';
|
||||
key: string;
|
||||
rowTitle?: string;
|
||||
rowDescription?: string;
|
||||
label?: string;
|
||||
helpText?: string;
|
||||
placeholder?: string;
|
||||
labelAppend?: string;
|
||||
settings?: SettingDefinition[];
|
||||
validation?: SettingValidation;
|
||||
required?: boolean;
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
export type SettingDefinition = Setting | AdvancedSettings;
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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 { getAgentAuthorizationSettings } from './agent_authorization_settings';
|
||||
import { SettingsRow } from '../typings';
|
||||
import { isSettingsFormValid } from '../settings_form/utils';
|
||||
|
||||
describe('apm-fleet-apm-integration', () => {
|
||||
describe('getAgentAuthorizationSettings', () => {
|
||||
function findSetting(key: string, settings: SettingsRow[]) {
|
||||
return settings.find(
|
||||
(setting) => setting.type !== 'advanced_setting' && setting.key === key
|
||||
);
|
||||
}
|
||||
it('returns read only secret token when on cloud', () => {
|
||||
const settings = getAgentAuthorizationSettings({ isCloudPolicy: true });
|
||||
const secretToken = findSetting('secret_token', settings);
|
||||
expect(secretToken).toEqual({
|
||||
type: 'text',
|
||||
key: 'secret_token',
|
||||
readOnly: true,
|
||||
labelAppend: 'Optional',
|
||||
label: 'Secret token',
|
||||
});
|
||||
});
|
||||
it('returns secret token when NOT on cloud', () => {
|
||||
const settings = getAgentAuthorizationSettings({ isCloudPolicy: false });
|
||||
const secretToken = findSetting('secret_token', settings);
|
||||
|
||||
expect(secretToken).toEqual({
|
||||
type: 'text',
|
||||
key: 'secret_token',
|
||||
readOnly: false,
|
||||
labelAppend: 'Optional',
|
||||
label: 'Secret token',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAgentAuthorizationFormValid', () => {
|
||||
describe('validates integer fields', () => {
|
||||
[
|
||||
'api_key_limit',
|
||||
'anonymous_rate_limit_ip_limit',
|
||||
'anonymous_rate_limit_event_limit',
|
||||
].map((key) => {
|
||||
it(`returns false when ${key} is lower than 1`, () => {
|
||||
const settings = getAgentAuthorizationSettings({
|
||||
isCloudPolicy: true,
|
||||
});
|
||||
expect(
|
||||
isSettingsFormValid(settings, {
|
||||
[key]: { value: 0, type: 'integer' },
|
||||
})
|
||||
).toBeFalsy();
|
||||
|
||||
expect(
|
||||
isSettingsFormValid(settings, {
|
||||
[key]: { value: -1, type: 'integer' },
|
||||
})
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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';
|
||||
import { getIntegerRt } from '../../../../../common/agent_configuration/runtime_types/integer_rt';
|
||||
import { OPTIONAL_LABEL } from '../settings_form/utils';
|
||||
import { SettingsRow } from '../typings';
|
||||
|
||||
export function getAgentAuthorizationSettings({
|
||||
isCloudPolicy,
|
||||
}: {
|
||||
isCloudPolicy: boolean;
|
||||
}): SettingsRow[] {
|
||||
return [
|
||||
{
|
||||
type: 'boolean',
|
||||
key: 'api_key_enabled',
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
placeholder: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.apiKeyAuthenticationPlaceholder',
|
||||
{ defaultMessage: 'API key for agent authentication' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.apiKeyAuthenticationHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Enable API Key auth between APM Server and APM Agents.',
|
||||
}
|
||||
),
|
||||
settings: [
|
||||
{
|
||||
key: 'api_key_limit',
|
||||
type: 'integer',
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.apiKeyLimitLabel',
|
||||
{ defaultMessage: 'Number of keys' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.apiKeyLimitHelpText',
|
||||
{ defaultMessage: 'Might be used for security policy compliance.' }
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.apiKeyLimitTitle',
|
||||
{
|
||||
defaultMessage:
|
||||
'Maximum number of API keys of Agent authentication',
|
||||
}
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.apiKeyLimitDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Restrict number of unique API keys per minute, used for auth between APM Agents and Server.',
|
||||
}
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
key: 'secret_token',
|
||||
readOnly: isCloudPolicy,
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.secretTokenLabel',
|
||||
{ defaultMessage: 'Secret token' }
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'boolean',
|
||||
key: 'anonymous_enabled',
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousEnabledTitle',
|
||||
{ defaultMessage: 'Anonymous Agent access' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousEnabledHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Enable anonymous access to APM Server for select APM Agents.',
|
||||
}
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousEnabledDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Allow anonymous access only for specified agents and/or services. This is primarily intended to allow limited access for untrusted agents, such as Real User Monitoring. When anonymous auth is enabled, only agents matching the Allowed Agents and services matching the Allowed Services configuration are allowed. See below for details on default values.',
|
||||
}
|
||||
),
|
||||
settings: [
|
||||
{
|
||||
type: 'combo',
|
||||
key: 'anonymous_allow_agent',
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousAllowAgentLabel',
|
||||
{ defaultMessage: 'Allowed agents' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousAllowAgentHelpText',
|
||||
{
|
||||
defaultMessage: 'Allowed agent names for anonymous access.',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'combo',
|
||||
key: 'anonymous_allow_service',
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousAllowServiceLabel',
|
||||
{ defaultMessage: 'Allowed services' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousAllowServiceHelpText',
|
||||
{
|
||||
defaultMessage: 'Allowed service names for anonymous access.',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'anonymous_rate_limit_ip_limit',
|
||||
type: 'integer',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousRateLimitIpLimitLabel',
|
||||
{ defaultMessage: 'Rate limit (IP limit)' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousRateLimitIpLimitHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Number of unique client IPs for which a distinct rate limit will be maintained.',
|
||||
}
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
},
|
||||
{
|
||||
key: 'anonymous_rate_limit_event_limit',
|
||||
type: 'integer',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousRateLimitEventLimitLabel',
|
||||
{
|
||||
defaultMessage: 'Event rate limit (event limit)',
|
||||
}
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.agentAuthorization.anonymousRateLimitEventLimitHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Maximum number of events per client IP per second.',
|
||||
}
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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 { getApmSettings } from './apm_settings';
|
||||
import { SettingsRow, BasicSettingRow } from '../typings';
|
||||
import { isSettingsFormValid } from '../settings_form/utils';
|
||||
|
||||
describe('apm_settings', () => {
|
||||
describe('getApmSettings', () => {
|
||||
function findSetting(key: string, settings: SettingsRow[]) {
|
||||
return settings.find(
|
||||
(setting) => setting.type !== 'advanced_setting' && setting.key === key
|
||||
) as BasicSettingRow;
|
||||
}
|
||||
['host', 'url'].map((key) => {
|
||||
it(`returns read only ${key} when on cloud`, () => {
|
||||
const settings = getApmSettings({ isCloudPolicy: true });
|
||||
const setting = findSetting(key, settings);
|
||||
expect(setting.readOnly).toBeTruthy();
|
||||
});
|
||||
it(`returns ${key} when NOT on cloud`, () => {
|
||||
const settings = getApmSettings({ isCloudPolicy: false });
|
||||
const setting = findSetting(key, settings);
|
||||
expect(setting.readOnly).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAPMFormValid', () => {
|
||||
describe('validates integer fields', () => {
|
||||
['max_header_bytes', 'max_event_bytes'].map((key) => {
|
||||
it(`returns false when ${key} is lower than 1`, () => {
|
||||
const settings = getApmSettings({ isCloudPolicy: true });
|
||||
expect(
|
||||
isSettingsFormValid(settings, {
|
||||
[key]: { value: 0, type: 'integer' },
|
||||
})
|
||||
).toBeFalsy();
|
||||
|
||||
expect(
|
||||
isSettingsFormValid(settings, {
|
||||
[key]: { value: -1, type: 'integer' },
|
||||
})
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
['max_connections'].map((key) => {
|
||||
it(`returns false when ${key} is lower than 0`, () => {
|
||||
const settings = getApmSettings({ isCloudPolicy: true });
|
||||
expect(
|
||||
isSettingsFormValid(settings, {
|
||||
[key]: { value: -1, type: 'integer' },
|
||||
})
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('validates required fields', () => {
|
||||
['host', 'url'].map((key) => {
|
||||
it(`return false when ${key} is not defined`, () => {
|
||||
const settings = getApmSettings({ isCloudPolicy: true });
|
||||
expect(isSettingsFormValid(settings, {})).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('validates duration fields', () => {
|
||||
['idle_timeout', 'read_timeout', 'shutdown_timeout', 'write_timeout'].map(
|
||||
(key) => {
|
||||
it(`return false when ${key} lower then 1ms`, () => {
|
||||
const settings = getApmSettings({ isCloudPolicy: true });
|
||||
expect(
|
||||
isSettingsFormValid(settings, {
|
||||
[key]: { value: '0ms', type: 'text' },
|
||||
})
|
||||
).toBeFalsy();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -5,26 +5,16 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useMemo } from 'react';
|
||||
import { getDurationRt } from '../../../../../common/agent_configuration/runtime_types/duration_rt';
|
||||
import { getIntegerRt } from '../../../../../common/agent_configuration/runtime_types/integer_rt';
|
||||
import { OnFormChangeFn, PackagePolicyVars } from '../typings';
|
||||
import { SettingsForm } from './settings_form';
|
||||
import { SettingDefinition } from './typings';
|
||||
import {
|
||||
isSettingsFormValid,
|
||||
mergeNewVars,
|
||||
OPTIONAL_LABEL,
|
||||
REQUIRED_LABEL,
|
||||
} from './utils';
|
||||
import { OPTIONAL_LABEL, REQUIRED_LABEL } from '../settings_form/utils';
|
||||
import { SettingsRow } from '../typings';
|
||||
|
||||
interface Props {
|
||||
vars: PackagePolicyVars;
|
||||
onChange: OnFormChangeFn;
|
||||
export function getApmSettings({
|
||||
isCloudPolicy,
|
||||
}: {
|
||||
isCloudPolicy: boolean;
|
||||
}
|
||||
|
||||
function getApmSettings(isCloudPolicy: boolean): SettingDefinition[] {
|
||||
}): SettingsRow[] {
|
||||
return [
|
||||
{
|
||||
type: 'text',
|
||||
|
@ -63,33 +53,7 @@ function getApmSettings(isCloudPolicy: boolean): SettingDefinition[] {
|
|||
required: true,
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
key: 'secret_token',
|
||||
readOnly: isCloudPolicy,
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.secretTokenLabel',
|
||||
{ defaultMessage: 'Secret token' }
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'boolean',
|
||||
key: 'api_key_enabled',
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
placeholder: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.apiKeyAuthenticationPlaceholder',
|
||||
{ defaultMessage: 'API key for agent authentication' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.apiKeyAuthenticationHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Enable API Key auth between APM Server and APM Agents.',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'advanced_settings',
|
||||
type: 'advanced_setting',
|
||||
settings: [
|
||||
{
|
||||
key: 'max_header_bytes',
|
||||
|
@ -176,7 +140,11 @@ function getApmSettings(isCloudPolicy: boolean): SettingDefinition[] {
|
|||
'xpack.apm.fleet_integration.settings.apm.maxConnectionsLabel',
|
||||
{ defaultMessage: 'Simultaneously accepted connections' }
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.maxConnectionsHelpText',
|
||||
{ defaultMessage: '0 for unlimited' }
|
||||
),
|
||||
validation: getIntegerRt({ min: 0 }),
|
||||
},
|
||||
{
|
||||
key: 'response_headers',
|
||||
|
@ -202,34 +170,6 @@ function getApmSettings(isCloudPolicy: boolean): SettingDefinition[] {
|
|||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'api_key_limit',
|
||||
type: 'integer',
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.apiKeyLimitLabel',
|
||||
{ defaultMessage: 'Number of keys' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.apiKeyLimitHelpText',
|
||||
{ defaultMessage: 'Might be used for security policy compliance.' }
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.apiKeyLimitTitle',
|
||||
{
|
||||
defaultMessage:
|
||||
'Maximum number of API keys of Agent authentication',
|
||||
}
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.apiKeyLimitDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Restrict number of unique API keys per minute, used for auth between aPM Agents and Server.',
|
||||
}
|
||||
),
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
},
|
||||
{
|
||||
key: 'capture_personal_data',
|
||||
type: 'boolean',
|
||||
|
@ -279,28 +219,3 @@ function getApmSettings(isCloudPolicy: boolean): SettingDefinition[] {
|
|||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function APMSettingsForm({ vars, onChange, isCloudPolicy }: Props) {
|
||||
const apmSettings = useMemo(() => {
|
||||
return getApmSettings(isCloudPolicy);
|
||||
}, [isCloudPolicy]);
|
||||
|
||||
return (
|
||||
<SettingsForm
|
||||
title={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.settings.title',
|
||||
{ defaultMessage: 'General' }
|
||||
)}
|
||||
subtitle={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.apm.settings.subtitle',
|
||||
{ defaultMessage: 'Settings for the APM integration.' }
|
||||
)}
|
||||
settings={apmSettings}
|
||||
vars={vars}
|
||||
onChange={(key, value) => {
|
||||
const newVars = mergeNewVars(vars, key, value);
|
||||
onChange(newVars, isSettingsFormValid(apmSettings, newVars));
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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';
|
||||
import { PackagePolicyVars, SettingsRow } from '../typings';
|
||||
import { isSettingsFormValid, OPTIONAL_LABEL } from '../settings_form/utils';
|
||||
|
||||
const ENABLE_RUM_KEY = 'enable_rum';
|
||||
export function getRUMSettings(): SettingsRow[] {
|
||||
return [
|
||||
{
|
||||
key: ENABLE_RUM_KEY,
|
||||
type: 'boolean',
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.enableRumTitle',
|
||||
{ defaultMessage: 'Enable RUM' }
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.enableRumDescription',
|
||||
{ defaultMessage: 'Enable Real User Monitoring (RUM)' }
|
||||
),
|
||||
settings: [
|
||||
{
|
||||
key: 'rum_allow_origins',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowOriginsLabel',
|
||||
{ defaultMessage: 'Origin Headers' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowOriginsHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Allowed Origin headers to be sent by User Agents.',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'rum_allow_headers',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderLabel',
|
||||
{ defaultMessage: 'Access-Control-Allow-Headers' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Supported Access-Control-Allow-Headers in addition to "Content-Type", "Content-Encoding" and "Accept".',
|
||||
}
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderTitle',
|
||||
{ defaultMessage: 'Custom headers' }
|
||||
),
|
||||
rowDescription: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumAllowHeaderDescription',
|
||||
{ defaultMessage: 'Configure authentication for the agent' }
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'rum_response_headers',
|
||||
type: 'area',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumResponseHeadersLabel',
|
||||
{ defaultMessage: 'Custom HTTP response headers' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumResponseHeadersHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Added to RUM responses, e.g. for security policy compliance.',
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
type: 'advanced_setting',
|
||||
settings: [
|
||||
{
|
||||
key: 'rum_library_pattern',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumLibraryPatternLabel',
|
||||
{ defaultMessage: 'Library Frame Pattern' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumLibraryPatternHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
"Identify library frames by matching a stacktrace frame's file_name and abs_path against this regexp.",
|
||||
}
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'rum_exclude_from_grouping',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumExcludeFromGroupingLabel',
|
||||
{ defaultMessage: 'Exclude from grouping' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.rum.rumExcludeFromGroupingHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
"Exclude stacktrace frames from error group calculations by matching a stacktrace frame's `file_name` against this regexp.",
|
||||
}
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function isRUMFormValid(
|
||||
newVars: PackagePolicyVars,
|
||||
rumSettings: SettingsRow[]
|
||||
) {
|
||||
// only validates RUM when its flag is enabled
|
||||
return (
|
||||
!newVars[ENABLE_RUM_KEY].value || isSettingsFormValid(rumSettings, newVars)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 { getTLSSettings, isTLSFormValid } from './tls_settings';
|
||||
|
||||
describe('tls_settings', () => {
|
||||
describe('isTLSFormValid', () => {
|
||||
describe('validates duration fields', () => {
|
||||
['tls_certificate', 'tls_key'].map((key) => {
|
||||
it(`return false when ${key} lower then 1ms`, () => {
|
||||
const settings = getTLSSettings();
|
||||
expect(
|
||||
isTLSFormValid(
|
||||
{ tls_enabled: { value: true, type: 'bool' } },
|
||||
settings
|
||||
)
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('returns true when tls_enabled is disabled', () => {
|
||||
const settings = getTLSSettings();
|
||||
expect(
|
||||
isTLSFormValid(
|
||||
{ tls_enabled: { value: false, type: 'bool' } },
|
||||
settings
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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';
|
||||
import { PackagePolicyVars, SettingsRow } from '../typings';
|
||||
import {
|
||||
isSettingsFormValid,
|
||||
OPTIONAL_LABEL,
|
||||
REQUIRED_LABEL,
|
||||
} from '../settings_form/utils';
|
||||
|
||||
const TLS_ENABLED_KEY = 'tls_enabled';
|
||||
|
||||
export function getTLSSettings(): SettingsRow[] {
|
||||
return [
|
||||
{
|
||||
key: TLS_ENABLED_KEY,
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsEnabledTitle',
|
||||
{ defaultMessage: 'Enable TLS' }
|
||||
),
|
||||
type: 'boolean',
|
||||
settings: [
|
||||
{
|
||||
key: 'tls_certificate',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCertificateLabel',
|
||||
{ defaultMessage: 'File path to server certificate' }
|
||||
),
|
||||
rowTitle: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCertificateTitle',
|
||||
{ defaultMessage: 'TLS certificate' }
|
||||
),
|
||||
labelAppend: REQUIRED_LABEL,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'tls_key',
|
||||
type: 'text',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsKeyLabel',
|
||||
{ defaultMessage: 'File path to server certificate key' }
|
||||
),
|
||||
labelAppend: REQUIRED_LABEL,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
key: 'tls_supported_protocols',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsSupportedProtocolsLabel',
|
||||
{ defaultMessage: 'Supported protocol versions' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
},
|
||||
{
|
||||
key: 'tls_cipher_suites',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesLabel',
|
||||
{ defaultMessage: 'Cipher suites for TLS connections' }
|
||||
),
|
||||
helpText: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCipherSuitesHelpText',
|
||||
{ defaultMessage: 'Not configurable for TLS 1.3.' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
},
|
||||
{
|
||||
key: 'tls_curve_types',
|
||||
type: 'combo',
|
||||
label: i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.tls.tlsCurveTypesLabel',
|
||||
{ defaultMessage: 'Curve types for ECDHE based cipher suites' }
|
||||
),
|
||||
labelAppend: OPTIONAL_LABEL,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function isTLSFormValid(
|
||||
newVars: PackagePolicyVars,
|
||||
tlsSettings: SettingsRow[]
|
||||
) {
|
||||
// only validates TLS when its flag is enabled
|
||||
return (
|
||||
!newVars[TLS_ENABLED_KEY].value || isSettingsFormValid(tlsSettings, newVars)
|
||||
);
|
||||
}
|
|
@ -15,11 +15,11 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { FormRowOnChange } from './settings_form';
|
||||
import { SettingDefinition } from './typings';
|
||||
import { FormRowOnChange } from './';
|
||||
import { SettingsRow } from '../typings';
|
||||
|
||||
interface Props {
|
||||
setting: SettingDefinition;
|
||||
row: SettingsRow;
|
||||
value?: any;
|
||||
onChange: FormRowOnChange;
|
||||
}
|
||||
|
@ -33,17 +33,15 @@ const DISABLED_LABEL = i18n.translate(
|
|||
{ defaultMessage: 'Disabled' }
|
||||
);
|
||||
|
||||
export function FormRowSetting({ setting, value, onChange }: Props) {
|
||||
switch (setting.type) {
|
||||
export function FormRowSetting({ row, value, onChange }: Props) {
|
||||
switch (row.type) {
|
||||
case 'boolean': {
|
||||
return (
|
||||
<EuiSwitch
|
||||
label={
|
||||
setting.placeholder || (value ? ENABLED_LABEL : DISABLED_LABEL)
|
||||
}
|
||||
label={row.placeholder || (value ? ENABLED_LABEL : DISABLED_LABEL)}
|
||||
checked={value}
|
||||
onChange={(e) => {
|
||||
onChange(setting.key, e.target.checked);
|
||||
onChange(row.key, e.target.checked);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -52,11 +50,11 @@ export function FormRowSetting({ setting, value, onChange }: Props) {
|
|||
case 'text': {
|
||||
return (
|
||||
<EuiFieldText
|
||||
readOnly={setting.readOnly}
|
||||
readOnly={row.readOnly}
|
||||
value={value}
|
||||
prepend={setting.readOnly ? <EuiIcon type="lock" /> : undefined}
|
||||
prepend={row.readOnly ? <EuiIcon type="lock" /> : undefined}
|
||||
onChange={(e) => {
|
||||
onChange(setting.key, e.target.value);
|
||||
onChange(row.key, e.target.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -66,7 +64,7 @@ export function FormRowSetting({ setting, value, onChange }: Props) {
|
|||
<EuiTextArea
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(setting.key, e.target.value);
|
||||
onChange(row.key, e.target.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -77,7 +75,7 @@ export function FormRowSetting({ setting, value, onChange }: Props) {
|
|||
<EuiFieldNumber
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(setting.key, e.target.value);
|
||||
onChange(row.key, e.target.value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -88,6 +86,7 @@ export function FormRowSetting({ setting, value, onChange }: Props) {
|
|||
: [];
|
||||
return (
|
||||
<EuiComboBox
|
||||
noSuggestions
|
||||
placeholder={i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.selectOrCreateOptions',
|
||||
{ defaultMessage: 'Select or create options' }
|
||||
|
@ -96,18 +95,18 @@ export function FormRowSetting({ setting, value, onChange }: Props) {
|
|||
selectedOptions={comboOptions}
|
||||
onChange={(option) => {
|
||||
onChange(
|
||||
setting.key,
|
||||
row.key,
|
||||
option.map(({ label }) => label)
|
||||
);
|
||||
}}
|
||||
onCreateOption={(newOption) => {
|
||||
onChange(setting.key, [...value, newOption]);
|
||||
onChange(row.key, [...value, newOption]);
|
||||
}}
|
||||
isClearable={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unknown type "${setting.type}"`);
|
||||
throw new Error(`Unknown type "${row.type}"`);
|
||||
}
|
||||
}
|
|
@ -17,9 +17,8 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useState } from 'react';
|
||||
import { PackagePolicyVars } from '../typings';
|
||||
import { PackagePolicyVars, SettingsRow } from '../typings';
|
||||
import { FormRowSetting } from './form_row_setting';
|
||||
import { SettingDefinition } from './typings';
|
||||
import { validateSettingValue } from './utils';
|
||||
|
||||
export type FormRowOnChange = (key: string, value: any) => void;
|
||||
|
@ -29,73 +28,74 @@ function FormRow({
|
|||
vars,
|
||||
onChange,
|
||||
}: {
|
||||
initialSetting: SettingDefinition;
|
||||
initialSetting: SettingsRow;
|
||||
vars?: PackagePolicyVars;
|
||||
onChange: FormRowOnChange;
|
||||
}) {
|
||||
function getSettingFormRow(setting: SettingDefinition) {
|
||||
if (setting.type === 'advanced_settings') {
|
||||
function getSettingFormRow(row: SettingsRow) {
|
||||
if (row.type === 'advanced_setting') {
|
||||
return (
|
||||
<AdvancedOptions>
|
||||
{setting.settings.map((advancedSetting) =>
|
||||
{row.settings.map((advancedSetting) =>
|
||||
getSettingFormRow(advancedSetting)
|
||||
)}
|
||||
</AdvancedOptions>
|
||||
);
|
||||
} else {
|
||||
const { key } = setting;
|
||||
const value = vars?.[key]?.value;
|
||||
const { isValid, message } = validateSettingValue(setting, value);
|
||||
return (
|
||||
<React.Fragment key={key}>
|
||||
<EuiDescribedFormGroup
|
||||
title={<h3>{setting.rowTitle}</h3>}
|
||||
description={setting.rowDescription}
|
||||
>
|
||||
<EuiFormRow
|
||||
label={setting.label}
|
||||
isInvalid={!isValid}
|
||||
error={isValid ? undefined : message}
|
||||
helpText={<EuiText size="xs">{setting.helpText}</EuiText>}
|
||||
labelAppend={
|
||||
<EuiText size="xs" color="subdued">
|
||||
{setting.labelAppend}
|
||||
</EuiText>
|
||||
}
|
||||
>
|
||||
<FormRowSetting
|
||||
setting={setting}
|
||||
onChange={onChange}
|
||||
value={value}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
{setting.settings &&
|
||||
value &&
|
||||
setting.settings.map((childSettings) =>
|
||||
getSettingFormRow(childSettings)
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
const { key } = row;
|
||||
const configEntry = vars?.[key];
|
||||
// hides a field that doesn't have its key defined in vars.
|
||||
// This is most likely to happen when a field is no longer supported in the current package version
|
||||
if (!configEntry) {
|
||||
return null;
|
||||
}
|
||||
const { value } = configEntry;
|
||||
const { isValid, message } = validateSettingValue(row, value);
|
||||
return (
|
||||
<React.Fragment key={key}>
|
||||
<EuiDescribedFormGroup
|
||||
title={<h3>{row.rowTitle}</h3>}
|
||||
description={row.rowDescription}
|
||||
>
|
||||
<EuiFormRow
|
||||
label={row.label}
|
||||
isInvalid={!isValid}
|
||||
error={isValid ? undefined : message}
|
||||
helpText={<EuiText size="xs">{row.helpText}</EuiText>}
|
||||
labelAppend={
|
||||
<EuiText size="xs" color="subdued">
|
||||
{row.labelAppend}
|
||||
</EuiText>
|
||||
}
|
||||
>
|
||||
<FormRowSetting row={row} onChange={onChange} value={value} />
|
||||
</EuiFormRow>
|
||||
</EuiDescribedFormGroup>
|
||||
{row.settings &&
|
||||
value &&
|
||||
row.settings.map((childSettings) => getSettingFormRow(childSettings))}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
return getSettingFormRow(initialSetting);
|
||||
}
|
||||
interface Props {
|
||||
|
||||
export interface SettingsSection {
|
||||
id: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
settings: SettingDefinition[];
|
||||
subtitle?: string;
|
||||
settings: SettingsRow[];
|
||||
}
|
||||
|
||||
interface Props {
|
||||
settingsSection: SettingsSection;
|
||||
vars?: PackagePolicyVars;
|
||||
onChange: FormRowOnChange;
|
||||
}
|
||||
|
||||
export function SettingsForm({
|
||||
title,
|
||||
subtitle,
|
||||
settings,
|
||||
vars,
|
||||
onChange,
|
||||
}: Props) {
|
||||
export function SettingsForm({ settingsSection, vars, onChange }: Props) {
|
||||
const { title, subtitle, settings } = settingsSection;
|
||||
return (
|
||||
<EuiPanel>
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
|
@ -104,11 +104,13 @@ export function SettingsForm({
|
|||
<h3>{title}</h3>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText size="s" color="subdued">
|
||||
{subtitle}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
{subtitle && (
|
||||
<EuiFlexItem>
|
||||
<EuiText size="s" color="subdued">
|
||||
{subtitle}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
|
@ -5,8 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import { getDurationRt } from '../../../../../common/agent_configuration/runtime_types/duration_rt';
|
||||
import { PackagePolicyVars } from '../typings';
|
||||
import { SettingDefinition } from './typings';
|
||||
import { getIntegerRt } from '../../../../../common/agent_configuration/runtime_types/integer_rt';
|
||||
import { PackagePolicyVars, SettingsRow } from '../typings';
|
||||
import {
|
||||
mergeNewVars,
|
||||
isSettingsFormValid,
|
||||
|
@ -16,7 +16,7 @@ import {
|
|||
describe('settings utils', () => {
|
||||
describe('validateSettingValue', () => {
|
||||
it('returns invalid when setting is required and value is empty', () => {
|
||||
const setting: SettingDefinition = {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
required: true,
|
||||
|
@ -27,17 +27,17 @@ describe('settings utils', () => {
|
|||
});
|
||||
});
|
||||
it('returns valid when setting is NOT required and value is empty', () => {
|
||||
const setting: SettingDefinition = {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
};
|
||||
expect(validateSettingValue(setting, undefined)).toEqual({
|
||||
isValid: true,
|
||||
message: '',
|
||||
message: 'Required field',
|
||||
});
|
||||
});
|
||||
it('returns valid when setting does not have a validation property', () => {
|
||||
const setting: SettingDefinition = {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
};
|
||||
|
@ -46,8 +46,8 @@ describe('settings utils', () => {
|
|||
message: '',
|
||||
});
|
||||
});
|
||||
it('returns valid after validating value', () => {
|
||||
const setting: SettingDefinition = {
|
||||
it('returns valid after validating duration value', () => {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
validation: getDurationRt({ min: '1ms' }),
|
||||
|
@ -57,8 +57,8 @@ describe('settings utils', () => {
|
|||
message: 'No errors!',
|
||||
});
|
||||
});
|
||||
it('returns invalid after validating value', () => {
|
||||
const setting: SettingDefinition = {
|
||||
it('returns invalid after validating duration value', () => {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
validation: getDurationRt({ min: '1ms' }),
|
||||
|
@ -68,9 +68,43 @@ describe('settings utils', () => {
|
|||
message: 'Must be greater than 1ms',
|
||||
});
|
||||
});
|
||||
it('returns valid after validating integer value', () => {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
};
|
||||
expect(validateSettingValue(setting, 1)).toEqual({
|
||||
isValid: true,
|
||||
message: 'No errors!',
|
||||
});
|
||||
});
|
||||
it('returns invalid after validating integer value', () => {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
validation: getIntegerRt({ min: 1 }),
|
||||
};
|
||||
expect(validateSettingValue(setting, 0)).toEqual({
|
||||
isValid: false,
|
||||
message: 'Must be greater than 1',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns valid when required and value is empty', () => {
|
||||
const setting: SettingsRow = {
|
||||
key: 'foo',
|
||||
type: 'text',
|
||||
required: true,
|
||||
};
|
||||
expect(validateSettingValue(setting, '')).toEqual({
|
||||
isValid: false,
|
||||
message: 'Required field',
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('isSettingsFormValid', () => {
|
||||
const settings: SettingDefinition[] = [
|
||||
const settings: SettingsRow[] = [
|
||||
{ key: 'foo', type: 'text', required: true },
|
||||
{
|
||||
key: 'bar',
|
||||
|
@ -79,7 +113,7 @@ describe('settings utils', () => {
|
|||
},
|
||||
{ key: 'baz', type: 'text', validation: getDurationRt({ min: '1ms' }) },
|
||||
{
|
||||
type: 'advanced_settings',
|
||||
type: 'advanced_setting',
|
||||
settings: [
|
||||
{
|
||||
type: 'text',
|
|
@ -8,9 +8,8 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { isRight } from 'fp-ts/lib/Either';
|
||||
import { PathReporter } from 'io-ts/lib/PathReporter';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { PackagePolicyVars } from '../typings';
|
||||
import { SettingDefinition, Setting } from './typings';
|
||||
import { isEmpty, isFinite } from 'lodash';
|
||||
import { PackagePolicyVars, SettingsRow, BasicSettingRow } from '../typings';
|
||||
|
||||
export const REQUIRED_LABEL = i18n.translate(
|
||||
'xpack.apm.fleet_integration.settings.requiredLabel',
|
||||
|
@ -34,13 +33,13 @@ export function mergeNewVars(
|
|||
}
|
||||
|
||||
export function isSettingsFormValid(
|
||||
parentSettings: SettingDefinition[],
|
||||
parentSettings: SettingsRow[],
|
||||
vars: PackagePolicyVars
|
||||
) {
|
||||
function isSettingsValid(settings: SettingDefinition[]): boolean {
|
||||
function isSettingsValid(settings: SettingsRow[]): boolean {
|
||||
return !settings
|
||||
.map((setting) => {
|
||||
if (setting.type === 'advanced_settings') {
|
||||
if (setting.type === 'advanced_setting') {
|
||||
return isSettingsValid(setting.settings);
|
||||
}
|
||||
|
||||
|
@ -59,11 +58,11 @@ export function isSettingsFormValid(
|
|||
return isSettingsValid(parentSettings);
|
||||
}
|
||||
|
||||
export function validateSettingValue(setting: Setting, value?: any) {
|
||||
if (isEmpty(value)) {
|
||||
export function validateSettingValue(setting: BasicSettingRow, value?: any) {
|
||||
if (!isFinite(value) && isEmpty(value)) {
|
||||
return {
|
||||
isValid: !setting.required,
|
||||
message: setting.required ? REQUIRED_FIELD : '',
|
||||
message: REQUIRED_FIELD,
|
||||
};
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import * as t from 'io-ts';
|
||||
import { PackagePolicyConfigRecordEntry } from '../../../../../fleet/common';
|
||||
|
||||
export {
|
||||
|
@ -19,7 +20,33 @@ export {
|
|||
|
||||
export type PackagePolicyVars = Record<string, PackagePolicyConfigRecordEntry>;
|
||||
|
||||
export type OnFormChangeFn = (
|
||||
newVars: PackagePolicyVars,
|
||||
isValid: boolean
|
||||
) => void;
|
||||
export type SettingValidation = t.Type<any, string, unknown>;
|
||||
|
||||
interface AdvancedSettingRow {
|
||||
type: 'advanced_setting';
|
||||
settings: SettingsRow[];
|
||||
}
|
||||
|
||||
export interface BasicSettingRow {
|
||||
type:
|
||||
| 'text'
|
||||
| 'combo'
|
||||
| 'area'
|
||||
| 'boolean'
|
||||
| 'integer'
|
||||
| 'bytes'
|
||||
| 'duration';
|
||||
key: string;
|
||||
rowTitle?: string;
|
||||
rowDescription?: string;
|
||||
label?: string;
|
||||
helpText?: string;
|
||||
placeholder?: string;
|
||||
labelAppend?: string;
|
||||
settings?: SettingsRow[];
|
||||
validation?: SettingValidation;
|
||||
required?: boolean;
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
export type SettingsRow = BasicSettingRow | AdvancedSettingRow;
|
||||
|
|
|
@ -72,7 +72,7 @@ function getFleetLink({
|
|||
}
|
||||
: {
|
||||
label: GET_STARTED_WITH_FLEET_LABEL,
|
||||
href: `${basePath}/app/integrations#/detail/apm-0.3.0/overview`,
|
||||
href: `${basePath}/app/integrations#/detail/apm-0.4.0/overview`,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ function TutorialFleetInstructions({ http, basePath, isDarkTheme }: Props) {
|
|||
<EuiButton
|
||||
iconType="analyzeEvent"
|
||||
color="secondary"
|
||||
href={`${basePath}/app/integrations#/detail/apm-0.3.0/overview`}
|
||||
href={`${basePath}/app/integrations#/detail/apm-0.4.0/overview`}
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.apm.tutorial.apmServer.fleet.apmIntegration.button',
|
||||
|
|
|
@ -32,7 +32,7 @@ export function getApmPackagePolicyDefinition(
|
|||
],
|
||||
package: {
|
||||
name: APM_PACKAGE_NAME,
|
||||
version: '0.3.0',
|
||||
version: '0.4.0',
|
||||
title: 'Elastic APM',
|
||||
},
|
||||
};
|
||||
|
@ -74,14 +74,6 @@ export const apmConfigMapping: Record<
|
|||
type: 'text',
|
||||
getValue: ({ cloudPluginSetup }) => cloudPluginSetup?.apm?.url,
|
||||
},
|
||||
'apm-server.secret_token': {
|
||||
name: 'secret_token',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.api_key.enabled': {
|
||||
name: 'api_key_enabled',
|
||||
type: 'bool',
|
||||
},
|
||||
'apm-server.rum.enabled': {
|
||||
name: 'enable_rum',
|
||||
type: 'bool',
|
||||
|
@ -90,10 +82,6 @@ export const apmConfigMapping: Record<
|
|||
name: 'default_service_environment',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.rum.allow_service_names': {
|
||||
name: 'rum_allow_service_names',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.rum.allow_origins': {
|
||||
name: 'rum_allow_origins',
|
||||
type: 'text',
|
||||
|
@ -106,14 +94,6 @@ export const apmConfigMapping: Record<
|
|||
name: 'rum_response_headers',
|
||||
type: 'yaml',
|
||||
},
|
||||
'apm-server.rum.event_rate.limit': {
|
||||
name: 'rum_event_rate_limit',
|
||||
type: 'integer',
|
||||
},
|
||||
'apm-server.rum.event_rate.lru_size': {
|
||||
name: 'rum_event_rate_lru_size',
|
||||
type: 'integer',
|
||||
},
|
||||
'apm-server.rum.library_pattern': {
|
||||
name: 'rum_library_pattern',
|
||||
type: 'text',
|
||||
|
@ -122,10 +102,6 @@ export const apmConfigMapping: Record<
|
|||
name: 'rum_exclude_from_grouping',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.api_key.limit': {
|
||||
name: 'api_key_limit',
|
||||
type: 'integer',
|
||||
},
|
||||
'apm-server.max_event_size': {
|
||||
name: 'max_event_bytes',
|
||||
type: 'integer',
|
||||
|
@ -190,4 +166,36 @@ export const apmConfigMapping: Record<
|
|||
name: 'tls_curve_types',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.auth.secret_token': {
|
||||
name: 'secret_token',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.auth.api_key.enabled': {
|
||||
name: 'api_key_enabled',
|
||||
type: 'bool',
|
||||
},
|
||||
'apm-server.auth.api_key.limit': {
|
||||
name: 'api_key_limit',
|
||||
type: 'bool',
|
||||
},
|
||||
'apm-server.auth.anonymous.enabled': {
|
||||
name: 'anonymous_enabled',
|
||||
type: 'bool',
|
||||
},
|
||||
'apm-server.auth.anonymous.allow_agent': {
|
||||
name: 'anonymous_allow_agent',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.auth.anonymous.allow_service': {
|
||||
name: 'anonymous_allow_service',
|
||||
type: 'text',
|
||||
},
|
||||
'apm-server.auth.anonymous.rate_limit.ip_limit': {
|
||||
name: 'anonymous_rate_limit_ip_limit',
|
||||
type: 'integer',
|
||||
},
|
||||
'apm-server.auth.anonymous.rate_limit.event_limit': {
|
||||
name: 'anonymous_rate_limit_event_limit',
|
||||
type: 'integer',
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue