"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Ja3FingerprintLink = exports.HostDetailsLink = exports.GoogleLink = exports.ExternalLink = exports.DEFAULT_NUMBER_OF_LINK = exports.DEFAULT_MORE_MAX_HEIGHT = exports.CreateCaseLink = exports.CertificateFingerprintLink = exports.CaseDetailsLink = void 0; Object.defineProperty(exports, "LinkAnchor", { enumerable: true, get: function () { return _helpers2.LinkAnchor; } }); Object.defineProperty(exports, "LinkButton", { enumerable: true, get: function () { return _helpers2.LinkButton; } }); exports.WhoIsLink = exports.UserDetailsLink = exports.SecuritySolutionLinkButton = exports.SecuritySolutionLinkAnchor = exports.ReputationLink = exports.PortOrServiceNameLink = exports.NetworkDetailsLink = void 0; Object.defineProperty(exports, "useGetSecuritySolutionLinkProps", { enumerable: true, get: function () { return _link_props.useGetSecuritySolutionLinkProps; } }); Object.defineProperty(exports, "useSecuritySolutionLinkProps", { enumerable: true, get: function () { return _link_props.useSecuritySolutionLinkProps; } }); Object.defineProperty(exports, "withSecuritySolutionLink", { enumerable: true, get: function () { return _link_props.withSecuritySolutionLink; } }); var _eui = require("@elastic/eui"); var _react = _interopRequireWildcard(require("react")); var _fp = require("lodash/fp"); var _tour_step = require("../guided_onboarding_tour/tour_step"); var _tour_config = require("../guided_onboarding_tour/tour_config"); var _guided_onboarding_tour = require("../guided_onboarding_tour"); var _constants = require("../../../../common/constants"); var _helpers = require("../../lib/helpers"); var _link_to = require("../link_to"); var _network = require("../../../../common/search_strategy/security_solution/network"); var _kibana = require("../../lib/kibana"); var _validators = require("../../utils/validators"); var i18n = _interopRequireWildcard(require("./translations")); var _types = require("../../../app/types"); var _redirect_to_users = require("../link_to/redirect_to_users"); var _helpers2 = require("./helpers"); var _link_props = require("./link_props"); 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; you may not use this file except in compliance with the Elastic License * 2.0. */ const DEFAULT_NUMBER_OF_LINK = 5; /** The default max-height of the Reputation Links popover used to show "+n More" items (e.g. `+9 More`) */ exports.DEFAULT_NUMBER_OF_LINK = DEFAULT_NUMBER_OF_LINK; const DEFAULT_MORE_MAX_HEIGHT = '200px'; // Internal Links exports.DEFAULT_MORE_MAX_HEIGHT = DEFAULT_MORE_MAX_HEIGHT; const UserDetailsLinkComponent = ({ children, Component, userName, isButton, onClick: onClickParam, title, userTab }) => { const encodedUserName = encodeURIComponent(userName); const { formatUrl, search } = (0, _link_to.useFormatUrl)(_types.SecurityPageName.users); const { application: { navigateToApp }, telemetry } = (0, _kibana.useKibana)().services; const goToUsersDetails = (0, _react.useCallback)(ev => { ev.preventDefault(); navigateToApp(_constants.APP_UI_ID, { deepLinkId: _types.SecurityPageName.users, path: userTab ? (0, _redirect_to_users.getTabsOnUsersDetailsUrl)(encodedUserName, userTab, search) : (0, _redirect_to_users.getUsersDetailsUrl)(encodedUserName, search) }); }, [encodedUserName, navigateToApp, search, userTab]); const href = (0, _react.useMemo)(() => formatUrl(userTab ? (0, _redirect_to_users.getTabsOnUsersDetailsUrl)(encodedUserName, userTab) : (0, _redirect_to_users.getUsersDetailsUrl)(encodedUserName)), [formatUrl, encodedUserName, userTab]); const onClick = (0, _react.useCallback)(e => { telemetry.reportEntityDetailsClicked({ entity: 'user' }); const callback = onClickParam !== null && onClickParam !== void 0 ? onClickParam : goToUsersDetails; callback(e); }, [goToUsersDetails, onClickParam, telemetry]); return isButton ? /*#__PURE__*/_react.default.createElement(_helpers2.GenericLinkButton, { Component: Component, dataTestSubj: "data-grid-user-details", href: href, onClick: onClick, title: title !== null && title !== void 0 ? title : userName }, children ? children : userName) : /*#__PURE__*/_react.default.createElement(_helpers2.LinkAnchor, { "data-test-subj": "users-link-anchor", onClick: onClick, href: href }, children ? children : userName); }; const UserDetailsLink = /*#__PURE__*/_react.default.memo(UserDetailsLinkComponent); exports.UserDetailsLink = UserDetailsLink; const HostDetailsLinkComponent = ({ children, Component, hostName, isButton, onClick: onClickParam, title, hostTab }) => { const { formatUrl, search } = (0, _link_to.useFormatUrl)(_types.SecurityPageName.hosts); const { application: { navigateToApp }, telemetry } = (0, _kibana.useKibana)().services; const encodedHostName = encodeURIComponent(hostName); const goToHostDetails = (0, _react.useCallback)(ev => { ev.preventDefault(); navigateToApp(_constants.APP_UI_ID, { deepLinkId: _types.SecurityPageName.hosts, path: hostTab ? (0, _link_to.getTabsOnHostDetailsUrl)(encodedHostName, hostTab, search) : (0, _link_to.getHostDetailsUrl)(encodedHostName, search) }); }, [encodedHostName, navigateToApp, search, hostTab]); const href = (0, _react.useMemo)(() => formatUrl(hostTab ? (0, _link_to.getTabsOnHostDetailsUrl)(encodedHostName, hostTab) : (0, _link_to.getHostDetailsUrl)(encodedHostName)), [formatUrl, encodedHostName, hostTab]); const onClick = (0, _react.useCallback)(e => { telemetry.reportEntityDetailsClicked({ entity: 'host' }); const callback = onClickParam !== null && onClickParam !== void 0 ? onClickParam : goToHostDetails; callback(e); }, [goToHostDetails, onClickParam, telemetry]); return isButton ? /*#__PURE__*/_react.default.createElement(_helpers2.GenericLinkButton, { Component: Component, dataTestSubj: "data-grid-host-details", href: href, iconType: "expand", onClick: onClick, title: title !== null && title !== void 0 ? title : hostName }, children) : /*#__PURE__*/_react.default.createElement(_helpers2.LinkAnchor, { onClick: onClick, href: href, "data-test-subj": "host-details-button" }, children ? children : hostName); }; const HostDetailsLink = /*#__PURE__*/_react.default.memo(HostDetailsLinkComponent); exports.HostDetailsLink = HostDetailsLink; const allowedUrlSchemes = ['http://', 'https://']; const ExternalLink = /*#__PURE__*/_react.default.memo(({ url, children, idx, overflowIndexStart = DEFAULT_NUMBER_OF_LINK, allItemsLimit = DEFAULT_NUMBER_OF_LINK }) => { const lastVisibleItemIndex = overflowIndexStart - 1; const lastItemIndex = allItemsLimit - 1; const lastIndexToShow = Math.max(0, Math.min(lastVisibleItemIndex, lastItemIndex)); const inAllowlist = allowedUrlSchemes.some(scheme => url.indexOf(scheme) === 0); return url && inAllowlist && !(0, _validators.isUrlInvalid)(url) && children ? /*#__PURE__*/_react.default.createElement(_eui.EuiToolTip, { content: url, position: "top", "data-test-subj": "externalLinkTooltip" }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { href: url, target: "_blank", rel: "noopener", "data-test-subj": "externalLink" }, children), !(0, _fp.isNil)(idx) && idx < lastIndexToShow && /*#__PURE__*/_react.default.createElement(_helpers2.Comma, { "data-test-subj": "externalLinkComma" }))) : null; }); exports.ExternalLink = ExternalLink; ExternalLink.displayName = 'ExternalLink'; const NetworkDetailsLinkComponent = ({ Component, children, ip, flowTarget = _network.FlowTarget.source, isButton, onClick, title }) => { const getSecuritySolutionLinkProps = (0, _link_props.useGetSecuritySolutionLinkProps)(); const getLink = (0, _react.useCallback)((cIp, i) => { const { onClick: onClickNavigation, href } = getSecuritySolutionLinkProps({ deepLinkId: _types.SecurityPageName.network, path: (0, _link_to.getNetworkDetailsUrl)(encodeURIComponent((0, _helpers.encodeIpv6)(cIp)), flowTarget) }); const onLinkClick = onClick !== null && onClick !== void 0 ? onClick : e => onClickNavigation(e); return isButton ? /*#__PURE__*/_react.default.createElement(_helpers2.GenericLinkButton, { Component: Component, key: `${cIp}-${i}`, dataTestSubj: "data-grid-network-details", onClick: onLinkClick, href: href, title: title !== null && title !== void 0 ? title : cIp }, children) : /*#__PURE__*/_react.default.createElement(_helpers2.LinkAnchor, { key: `${cIp}-${i}`, onClick: onLinkClick, href: href, "data-test-subj": "network-details" }, children ? children : cIp); }, [children, Component, flowTarget, getSecuritySolutionLinkProps, onClick, isButton, title]); return (0, _fp.isArray)(ip) ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, ip.map(getLink)) : getLink(ip, 0); }; const NetworkDetailsLink = /*#__PURE__*/_react.default.memo(NetworkDetailsLinkComponent); exports.NetworkDetailsLink = NetworkDetailsLink; const CaseDetailsLinkComponent = ({ index, children, detailName, title }) => { const { formatUrl, search } = (0, _link_to.useFormatUrl)(_types.SecurityPageName.case); const { navigateToApp } = (0, _kibana.useKibana)().services.application; const { activeStep, isTourShown } = (0, _guided_onboarding_tour.useTourContext)(); const isTourStepActive = (0, _react.useMemo)(() => activeStep === _tour_config.AlertsCasesTourSteps.viewCase && isTourShown(_tour_config.SecurityStepId.alertsCases) && index === 0, [activeStep, index, isTourShown]); const goToCaseDetails = (0, _react.useCallback)(async ev => { if (ev) ev.preventDefault(); return navigateToApp(_constants.APP_UI_ID, { deepLinkId: _types.SecurityPageName.case, path: (0, _link_to.getCaseDetailsUrl)({ id: detailName, search }) }); }, [detailName, navigateToApp, search]); (0, _react.useEffect)(() => { var _document$querySelect; if (isTourStepActive) (_document$querySelect = document.querySelector(`[tour-step="RelatedCases-accordion"]`)) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.scrollIntoView(); }, [isTourStepActive]); return /*#__PURE__*/_react.default.createElement(_tour_step.GuidedOnboardingTourStep, { onClick: goToCaseDetails, isTourAnchor: isTourStepActive, step: _tour_config.AlertsCasesTourSteps.viewCase, tourId: _tour_config.SecurityStepId.alertsCases }, /*#__PURE__*/_react.default.createElement(_helpers2.LinkAnchor, { onClick: goToCaseDetails, href: formatUrl((0, _link_to.getCaseDetailsUrl)({ id: detailName })), "data-test-subj": "case-details-link", "aria-label": i18n.CASE_DETAILS_LINK_ARIA(title !== null && title !== void 0 ? title : detailName) }, children ? children : detailName)); }; const CaseDetailsLink = /*#__PURE__*/_react.default.memo(CaseDetailsLinkComponent); exports.CaseDetailsLink = CaseDetailsLink; CaseDetailsLink.displayName = 'CaseDetailsLink'; const CreateCaseLink = /*#__PURE__*/_react.default.memo(({ children }) => { const { formatUrl, search } = (0, _link_to.useFormatUrl)(_types.SecurityPageName.case); const { navigateToApp } = (0, _kibana.useKibana)().services.application; const goToCreateCase = (0, _react.useCallback)(async ev => { ev.preventDefault(); return navigateToApp(_constants.APP_UI_ID, { deepLinkId: _types.SecurityPageName.case, path: (0, _link_to.getCreateCaseUrl)(search) }); }, [navigateToApp, search]); return /*#__PURE__*/_react.default.createElement(_helpers2.LinkAnchor, { onClick: goToCreateCase, href: formatUrl((0, _link_to.getCreateCaseUrl)()) }, children); }); exports.CreateCaseLink = CreateCaseLink; CreateCaseLink.displayName = 'CreateCaseLink'; // External Links const GoogleLink = /*#__PURE__*/_react.default.memo(({ children, link }) => { const url = (0, _react.useMemo)(() => `https://www.google.com/search?q=${encodeURIComponent(link)}`, [link]); return /*#__PURE__*/_react.default.createElement(ExternalLink, { url: url }, children ? children : link); }); exports.GoogleLink = GoogleLink; GoogleLink.displayName = 'GoogleLink'; const PortOrServiceNameLink = /*#__PURE__*/_react.default.memo(({ Component, title, children, portOrServiceName }) => { var _ref; const href = (0, _react.useMemo)(() => `https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=${encodeURIComponent(String(portOrServiceName))}`, [portOrServiceName]); return Component ? /*#__PURE__*/_react.default.createElement(Component, { href: href, "data-test-subj": "data-grid-port-or-service-name-link", title: title, iconType: "link" }, (_ref = title !== null && title !== void 0 ? title : children) !== null && _ref !== void 0 ? _ref : portOrServiceName) : /*#__PURE__*/_react.default.createElement(_helpers2.PortContainer, null, /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { "data-test-subj": "port-or-service-name-link", href: href, target: "_blank" }, children ? children : portOrServiceName)); }); exports.PortOrServiceNameLink = PortOrServiceNameLink; PortOrServiceNameLink.displayName = 'PortOrServiceNameLink'; const Ja3FingerprintLink = /*#__PURE__*/_react.default.memo(({ children, ja3Fingerprint }) => { const href = (0, _react.useMemo)(() => `https://sslbl.abuse.ch/ja3-fingerprints/${encodeURIComponent(ja3Fingerprint)}`, [ja3Fingerprint]); return /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { "data-test-subj": "ja3-fingerprint-link", href: href, target: "_blank" }, children ? children : ja3Fingerprint); }); exports.Ja3FingerprintLink = Ja3FingerprintLink; Ja3FingerprintLink.displayName = 'Ja3FingerprintLink'; const CertificateFingerprintLink = /*#__PURE__*/_react.default.memo(({ children, certificateFingerprint }) => { const href = (0, _react.useMemo)(() => `https://sslbl.abuse.ch/ssl-certificates/sha1/${encodeURIComponent(certificateFingerprint)}`, [certificateFingerprint]); return /*#__PURE__*/_react.default.createElement(_eui.EuiLink, { "data-test-subj": "certificate-fingerprint-link", href: href, target: "_blank" }, children ? children : certificateFingerprint); }); exports.CertificateFingerprintLink = CertificateFingerprintLink; CertificateFingerprintLink.displayName = 'CertificateFingerprintLink'; var DefaultReputationLink; (function (DefaultReputationLink) { DefaultReputationLink["virustotal.com"] = "virustotal.com"; DefaultReputationLink["talosIntelligence.com"] = "talosIntelligence.com"; })(DefaultReputationLink || (DefaultReputationLink = {})); function isDefaultReputationLink(name) { return name === DefaultReputationLink['virustotal.com'] || name === DefaultReputationLink['talosIntelligence.com']; } const isReputationLink = rowItem => rowItem.url_template !== undefined && rowItem.name !== undefined; const defaultNameMapping = { [DefaultReputationLink['virustotal.com']]: i18n.VIEW_VIRUS_TOTAL, [DefaultReputationLink['talosIntelligence.com']]: i18n.VIEW_TALOS_INTELLIGENCE }; const ReputationLinkComponent = ({ overflowIndexStart = DEFAULT_NUMBER_OF_LINK, allItemsLimit = DEFAULT_NUMBER_OF_LINK, showDomain = false, domain, direction = 'row' }) => { const [ipReputationLinksSetting] = (0, _kibana.useUiSetting$)(_constants.IP_REPUTATION_LINKS_SETTING); const ipReputationLinks = (0, _react.useMemo)(() => ipReputationLinksSetting === null || ipReputationLinksSetting === void 0 ? void 0 : ipReputationLinksSetting.slice(0, allItemsLimit).filter( // eslint-disable-next-line @typescript-eslint/naming-convention ({ url_template, name }) => !(0, _fp.isNil)(url_template) && !(0, _fp.isNil)(name) && !(0, _validators.isUrlInvalid)(url_template)) // eslint-disable-next-line @typescript-eslint/naming-convention .map(({ name, url_template }) => ({ name: isDefaultReputationLink(name) ? defaultNameMapping[name] : name, url_template: url_template.replace(`{{ip}}`, encodeURIComponent(domain)) })), // eslint-disable-next-line react-hooks/exhaustive-deps [ipReputationLinksSetting, domain, defaultNameMapping, allItemsLimit]); const renderCallback = (0, _react.useCallback)(rowItem => { var _rowItem$name; return isReputationLink(rowItem) && /*#__PURE__*/_react.default.createElement(ExternalLink, { url: rowItem.url_template, overflowIndexStart: overflowIndexStart, allItemsLimit: allItemsLimit }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_rowItem$name = rowItem.name) !== null && _rowItem$name !== void 0 ? _rowItem$name : domain)); }, [allItemsLimit, domain, overflowIndexStart]); return (ipReputationLinks === null || ipReputationLinks === void 0 ? void 0 : ipReputationLinks.length) > 0 ? /*#__PURE__*/_react.default.createElement("section", null, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { gutterSize: "none", justifyContent: "center", direction: direction, alignItems: "center", "data-test-subj": "reputationLinkGroup" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: true }, ipReputationLinks === null || ipReputationLinks === void 0 ? void 0 : ipReputationLinks.slice(0, overflowIndexStart).map(({ name, url_template: urlTemplate }, id) => /*#__PURE__*/_react.default.createElement(ExternalLink, { allItemsLimit: ipReputationLinks.length, idx: id, overflowIndexStart: overflowIndexStart, url: urlTemplate, "data-test-subj": "externalLinkComponent", key: `reputationLink-${id}` }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, showDomain ? domain : name !== null && name !== void 0 ? name : domain)))), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_helpers2.ReputationLinksOverflow, { rowItems: ipReputationLinks, render: renderCallback, moreMaxHeight: DEFAULT_MORE_MAX_HEIGHT, overflowIndexStart: overflowIndexStart })))) : null; }; ReputationLinkComponent.displayName = 'ReputationLinkComponent'; const ReputationLink = /*#__PURE__*/_react.default.memo(ReputationLinkComponent); exports.ReputationLink = ReputationLink; const WhoIsLink = /*#__PURE__*/_react.default.memo(({ children, domain }) => { const url = (0, _react.useMemo)(() => `https://www.iana.org/whois?q=${encodeURIComponent(domain)}`, [domain]); return /*#__PURE__*/_react.default.createElement(ExternalLink, { url: url }, children ? children : domain); }); exports.WhoIsLink = WhoIsLink; WhoIsLink.displayName = 'WhoIsLink'; /** * Security Solutions internal link button. * * `;` */ const SecuritySolutionLinkButton = (0, _link_props.withSecuritySolutionLink)(_helpers2.LinkButton); /** * Security Solutions internal link anchor. * * `;` */ exports.SecuritySolutionLinkButton = SecuritySolutionLinkButton; const SecuritySolutionLinkAnchor = (0, _link_props.withSecuritySolutionLink)(_helpers2.LinkAnchor); exports.SecuritySolutionLinkAnchor = SecuritySolutionLinkAnchor;