"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.ForgotPasswordPopover = exports.ClusterConfigurationForm = exports.CertificatePanel = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _eui = require("@elastic/eui"); var _react = _interopRequireWildcard(require("react")); var _useUpdateEffect = _interopRequireDefault(require("react-use/lib/useUpdateEffect")); var _i18n = require("@kbn/i18n"); var _i18nReact = require("@kbn/i18n-react"); var _uiTheme = require("@kbn/ui-theme"); var _doc_link = require("./doc_link"); var _get_command_line_snippet = require("./get_command_line_snippet"); var _submit_error_callout = require("./submit_error_callout"); var _text_truncate = require("./text_truncate"); var _use_form = require("./use_form"); var _use_html_id = require("./use_html_id"); var _use_kibana = require("./use_kibana"); var _use_verification = require("./use_verification"); var _use_visibility = require("./use_visibility"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * 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 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ const ClusterConfigurationForm = ({ host, authRequired, certificateChain, defaultValues = { username: 'kibana_system', password: '', caCert: '' }, onCancel, onSuccess }) => { const { http } = (0, _use_kibana.useKibana)(); const { status, getCode } = (0, _use_verification.useVerification)(); const [form, eventHandlers] = (0, _use_form.useForm)({ defaultValues, validate: values => { const errors = {}; if (authRequired) { if (!values.username) { errors.username = _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.usernameRequiredError', { defaultMessage: 'Enter a username.' }); } else if (values.username === 'elastic') { errors.username = _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.usernameReservedError', { defaultMessage: "User 'elastic' can't be used as the Kibana system user." }); } if (!values.password) { errors.password = _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.passwordRequiredError', { defaultMessage: 'Enter a password.' }); } } if (certificateChain && certificateChain.length > 0 && !values.caCert) { errors.caCert = _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.caCertConfirmationRequiredError', { defaultMessage: 'Confirm that you recognize and trust this certificate.' }); } return errors; }, onSubmit: async values => { await http.post('/internal/interactive_setup/configure', { body: JSON.stringify({ host, username: authRequired ? values.username : undefined, password: authRequired ? values.password : undefined, caCert: certificateChain && certificateChain.length > 0 ? values.caCert : undefined, code: getCode() }) }); onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(); } }); const [isVisible, buttonRef] = (0, _use_visibility.useVisibility)(); const trustCaCertId = (0, _use_html_id.useHtmlId)('clusterConfigurationForm', 'trustCaCert'); (0, _useUpdateEffect.default)(() => { if (status === 'verified' && isVisible) { form.submit(); } }, [status]); return /*#__PURE__*/_react.default.createElement(_eui.EuiForm, (0, _extends2.default)({ component: "form", noValidate: true }, eventHandlers), status !== 'unverified' && !form.isSubmitting && !form.isValidating && form.submitError && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_submit_error_callout.SubmitErrorCallout, { error: form.submitError, defaultTitle: _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.submitErrorTitle', { defaultMessage: "Couldn't configure Elastic" }) }), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, null)), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { responsive: false, alignItems: "center", gutterSize: "s" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false, className: "eui-textNoWrap" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.clusterConfigurationForm.connectTo", defaultMessage: "Connect to" })), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false, style: { overflow: 'hidden' } }, /*#__PURE__*/_react.default.createElement(_text_truncate.TextTruncate, null, /*#__PURE__*/_react.default.createElement("strong", null, host)))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, null), authRequired ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { label: _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.usernameLabel', { defaultMessage: 'Username' }), error: form.errors.username, isInvalid: form.touched.username && !!form.errors.username, fullWidth: true }, /*#__PURE__*/_react.default.createElement(_eui.EuiFieldText, { icon: "user", name: "username", value: form.values.username, isInvalid: form.touched.username && !!form.errors.username, fullWidth: true })), /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { label: _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.passwordLabel', { defaultMessage: 'Password' }), error: form.errors.password, isInvalid: form.touched.password && !!form.errors.password, helpText: form.errors.username ? undefined : /*#__PURE__*/_react.default.createElement(ForgotPasswordPopover, { username: form.values.username }), fullWidth: true }, /*#__PURE__*/_react.default.createElement(_eui.EuiFieldPassword, { type: "dual", name: "password", value: form.values.password, isInvalid: form.touched.password && !!form.errors.password, fullWidth: true })), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, null)) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiCallOut, { color: "warning", iconType: "warning", title: _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.insecureClusterTitle', { defaultMessage: 'This cluster is not secure' }), size: "s" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { tagName: "div", id: "interactiveSetup.clusterConfigurationForm.insecureClusterDescription", defaultMessage: "Anyone with the address can access your data." }), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "xs" }), /*#__PURE__*/_react.default.createElement(_doc_link.DocLink, { app: "elasticsearch", doc: "configuring-stack-security.html" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.clusterConfigurationForm.insecureClusterLink", defaultMessage: "Learn how to enable security features." }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, null)), certificateChain && certificateChain.length > 0 && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { label: _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.caCertLabel', { defaultMessage: 'Certificate authority' }), error: form.errors.caCert, isInvalid: form.touched.caCert && !!form.errors.caCert, fullWidth: true }, /*#__PURE__*/_react.default.createElement(_eui.EuiCheckableCard, { id: trustCaCertId, label: _i18n.i18n.translate('interactiveSetup.clusterConfigurationForm.trustCaCertLabel', { defaultMessage: 'I recognize and trust this certificate:' }), checkableType: "checkbox", value: "true", checked: !!form.values.caCert, onChange: () => { const rootCa = certificateChain[certificateChain.length - 1]; form.setTouched('caCert'); form.setValue('caCert', form.values.caCert ? '' : rootCa.raw); } }, /*#__PURE__*/_react.default.createElement(CertificateChain, { certificateChain: certificateChain }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, null)), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { responsive: false, justifyContent: "flexEnd" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonEmpty, { flush: "right", iconType: "arrowLeft", onClick: onCancel }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.clusterConfigurationForm.cancelButton", defaultMessage: "Back" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiButton, { buttonRef: buttonRef, type: "submit", isLoading: form.isSubmitting, isDisabled: form.isSubmitted && form.isInvalid, color: "primary", fill: true }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.clusterConfigurationForm.submitButton", defaultMessage: "{isSubmitting, select, true{Configuring Elastic\u2026} other{Configure Elastic}}", values: { isSubmitting: form.isSubmitting } }))))); }; exports.ClusterConfigurationForm = ClusterConfigurationForm; const CertificatePanel = ({ certificate, onClick, type, compressed = false }) => { return /*#__PURE__*/_react.default.createElement(_eui.EuiPanel, { color: compressed ? 'subdued' : undefined, hasBorder: !compressed }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { responsive: false, alignItems: "center", gutterSize: "m" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "document", size: "l" })), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { responsive: false, gutterSize: "none", justifyContent: "spaceBetween" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiTitle, { size: "xxs" }, /*#__PURE__*/_react.default.createElement("h3", null, certificate.subject.O || certificate.subject.CN))), !compressed && /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiBadge, null, type === 'root' ? _i18n.i18n.translate('interactiveSetup.certificatePanel.rootCertificateAuthority', { defaultMessage: 'Root CA' }) : type === 'intermediate' ? _i18n.i18n.translate('interactiveSetup.certificatePanel.intermediateCertificateAuthority', { defaultMessage: 'Intermediate CA' }) : _i18n.i18n.translate('interactiveSetup.certificatePanel.serverCertificate', { defaultMessage: 'Server certificate' })))), compressed && /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "xs" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.certificatePanel.issuer", defaultMessage: "Issued by: {issuer}", values: { issuer: onClick ? /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { onClick: onClick }, certificate.issuer.O || certificate.issuer.CN) : certificate.issuer.O || certificate.issuer.CN } })), !compressed && /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "xs" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.certificatePanel.validFrom", defaultMessage: "Issued on: {validFrom}", values: { validFrom: certificate.valid_from } })), /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "xs" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.certificatePanel.validTo", defaultMessage: "Expires on: {validTo}", values: { validTo: certificate.valid_to } })), !compressed && /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "xs" }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.certificatePanel.fingerprint", defaultMessage: "Fingerprint (SHA-256): {fingerprint}", values: { fingerprint: certificate.fingerprint256.replace(/\:/g, ' ') } }))))); }; exports.CertificatePanel = CertificatePanel; const CertificateChain = ({ certificateChain }) => { const [showModal, setShowModal] = (0, _react.useState)(false); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(CertificatePanel, { certificate: certificateChain[0], onClick: () => setShowModal(true), compressed: true }), showModal && /*#__PURE__*/_react.default.createElement(_eui.EuiModal, { onClose: () => setShowModal(false), maxWidth: _uiTheme.euiThemeVars.euiBreakpoints.s }, /*#__PURE__*/_react.default.createElement(_eui.EuiModalHeader, null, /*#__PURE__*/_react.default.createElement(_eui.EuiModalHeaderTitle, null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.certificateChain.title", defaultMessage: "Certificate chain" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiModalBody, null, certificateChain.slice().reverse().map(({ raw, ...certificate }, i) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, i > 0 && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "s" }), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { responsive: false, justifyContent: "center" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiIcon, { type: "sortDown", color: "subdued" }))), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "s" })), /*#__PURE__*/_react.default.createElement(CertificatePanel, { certificate: certificate, type: i === 0 ? 'root' : i < certificateChain.length - 1 ? 'intermediate' : undefined })))), /*#__PURE__*/_react.default.createElement(_eui.EuiModalFooter, null, /*#__PURE__*/_react.default.createElement(_eui.EuiButton, { fill: true, onClick: () => setShowModal(false) }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.certificateChain.cancelButton", defaultMessage: "Close" }))))); }; const ForgotPasswordPopover = ({ username }) => { const [isPopoverOpen, setIsPopoverOpen] = (0, _react.useState)(false); const button = /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { onClick: () => setIsPopoverOpen(isOpen => !isOpen) }, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.forgotPasswordPopover.buttonText", defaultMessage: "Forgot password?" })); return /*#__PURE__*/_react.default.createElement(_eui.EuiPopover, { button: button, anchorPosition: "rightCenter", isOpen: isPopoverOpen, closePopover: () => setIsPopoverOpen(false) }, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "s", grow: false }, /*#__PURE__*/_react.default.createElement("p", null, /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "interactiveSetup.forgotPasswordPopover.helpText", defaultMessage: "To reset the password for the {username} user, run the following command from the Elasticsearch installation directory:", values: { username: /*#__PURE__*/_react.default.createElement("strong", null, username) } })), /*#__PURE__*/_react.default.createElement(_eui.EuiCodeBlock, { language: "bash", paddingSize: "m", isCopyable: true }, (0, _get_command_line_snippet.getCommandLineSnippet)('elasticsearch-reset-password', `--username ${username}`)))); }; exports.ForgotPasswordPopover = ForgotPasswordPopover;