mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-02-23 23:23:59 +00:00
Compare commits
4 Commits
30.0-dev22
...
30.0-dev25
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
763b0e7362 | ||
|
|
e07e04377f | ||
|
|
3c8f63ed92 | ||
|
|
11a2246cb9 |
@@ -66,6 +66,7 @@ var filteringOptions *api.TrafficFilteringOptions // global
|
||||
var tapTargets []v1.Pod // global
|
||||
var packetSourceManager *source.PacketSourceManager // global
|
||||
var mainPacketInputChan chan source.TcpPacketInfo // global
|
||||
var tlsTapperInstance *tlstapper.TlsTapper // global
|
||||
|
||||
func inArrayInt(arr []int, valueToCheck int) bool {
|
||||
for _, value := range arr {
|
||||
@@ -92,7 +93,7 @@ func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem,
|
||||
if *tls {
|
||||
for _, e := range extensions {
|
||||
if e.Protocol.Name == "http" {
|
||||
startTlsTapper(e, outputItems, options)
|
||||
tlsTapperInstance = startTlsTapper(e, outputItems, options)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -106,20 +107,36 @@ func StartPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem,
|
||||
}
|
||||
|
||||
func UpdateTapTargets(newTapTargets []v1.Pod) {
|
||||
success := true
|
||||
|
||||
tapTargets = newTapTargets
|
||||
if err := initializePacketSources(); err != nil {
|
||||
logger.Log.Fatal(err)
|
||||
success = false
|
||||
}
|
||||
printNewTapTargets()
|
||||
|
||||
if tlsTapperInstance != nil {
|
||||
if err := tlstapper.UpdateTapTargets(tlsTapperInstance, &tapTargets, *procfs); err != nil {
|
||||
tlstapper.LogError(err)
|
||||
success = false
|
||||
}
|
||||
}
|
||||
|
||||
printNewTapTargets(success)
|
||||
}
|
||||
|
||||
func printNewTapTargets() {
|
||||
func printNewTapTargets(success bool) {
|
||||
printStr := ""
|
||||
for _, tapTarget := range tapTargets {
|
||||
printStr += fmt.Sprintf("%s (%s), ", tapTarget.Status.PodIP, tapTarget.Name)
|
||||
}
|
||||
printStr = strings.TrimRight(printStr, ", ")
|
||||
logger.Log.Infof("Now tapping: %s", printStr)
|
||||
|
||||
if success {
|
||||
logger.Log.Infof("Now tapping: %s", printStr)
|
||||
} else {
|
||||
logger.Log.Errorf("Failed to start tapping: %s", printStr)
|
||||
}
|
||||
}
|
||||
|
||||
func printPeriodicStats(cleaner *Cleaner) {
|
||||
@@ -236,13 +253,18 @@ func startPassiveTapper(opts *TapOpts, outputItems chan *api.OutputChannelItem)
|
||||
logger.Log.Infof("AppStats: %v", diagnose.AppStats)
|
||||
}
|
||||
|
||||
func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
||||
func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChannelItem, options *api.TrafficFilteringOptions) *tlstapper.TlsTapper {
|
||||
tls := tlstapper.TlsTapper{}
|
||||
tlsPerfBufferSize := os.Getpagesize() * 100
|
||||
|
||||
if err := tls.Init(tlsPerfBufferSize, *procfs, extension); err != nil {
|
||||
tlstapper.LogError(err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := tlstapper.UpdateTapTargets(&tls, &tapTargets, *procfs); err != nil {
|
||||
tlstapper.LogError(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// A quick way to instrument libssl.so without PID filtering - used for debuging and troubleshooting
|
||||
@@ -250,19 +272,16 @@ func startTlsTapper(extension *api.Extension, outputItems chan *api.OutputChanne
|
||||
if os.Getenv("MIZU_GLOBAL_SSL_LIBRARY") != "" {
|
||||
if err := tls.GlobalTap(os.Getenv("MIZU_GLOBAL_SSL_LIBRARY")); err != nil {
|
||||
tlstapper.LogError(err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := tlstapper.UpdateTapTargets(&tls, &tapTargets, *procfs); err != nil {
|
||||
tlstapper.LogError(err)
|
||||
return
|
||||
}
|
||||
|
||||
var emitter api.Emitter = &api.Emitting{
|
||||
AppStats: &diagnose.AppStats,
|
||||
OutputChannel: outputItems,
|
||||
}
|
||||
|
||||
go tls.Poll(emitter, options)
|
||||
|
||||
return &tls
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ func UpdateTapTargets(tls *TlsTapper, pods *[]v1.Pod, procfs string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tls.ClearPids()
|
||||
|
||||
for _, pid := range containerPids {
|
||||
if err := tls.AddPid(procfs, pid); err != nil {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
"github.com/up9inc/mizu/tap/api"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go tlsTapper bpf/tls_tapper.c -- -O2 -g -D__TARGET_ARCH_x86
|
||||
@@ -14,6 +15,7 @@ type TlsTapper struct {
|
||||
syscallHooks syscallHooks
|
||||
sslHooksStructs []sslHooks
|
||||
poller *tlsPoller
|
||||
registeredPids sync.Map
|
||||
}
|
||||
|
||||
func (t *TlsTapper) Init(bufferSize int, procfs string, extension *api.Extension) error {
|
||||
@@ -70,6 +72,16 @@ func (t *TlsTapper) RemovePid(pid uint32) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *TlsTapper) ClearPids() {
|
||||
t.registeredPids.Range(func(key, v interface{}) bool {
|
||||
if err := t.RemovePid(key.(uint32)); err != nil {
|
||||
LogError(err)
|
||||
}
|
||||
t.registeredPids.Delete(key)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TlsTapper) Close() []error {
|
||||
errors := make([]error, 0)
|
||||
|
||||
@@ -116,6 +128,8 @@ func (t *TlsTapper) tapPid(pid uint32, sslLibrary string) error {
|
||||
if err := pids.Put(pid, uint32(1)); err != nil {
|
||||
return errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
t.registeredPids.Store(pid, true)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
4
ui-common/package-lock.json
generated
4
ui-common/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@up9/mizu-common",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.135",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@up9/mizu-common",
|
||||
"version": "1.0.10",
|
||||
"version": "1.0.135",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@craco/craco": "^6.4.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@up9/mizu-common",
|
||||
"version": "1.0.135",
|
||||
"version": "1.0.137",
|
||||
"description": "Made with create-react-library",
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -11,6 +11,7 @@ import trafficViewerApi from "../../recoil/TrafficViewerApi";
|
||||
import TrafficViewerApi from "./TrafficViewerApi";
|
||||
import TrafficViewerApiAtom from "../../recoil/TrafficViewerApi/atom";
|
||||
import queryAtom from "../../recoil/query/atom";
|
||||
import useWindowDimensions, { useRequestTextByWidth } from "../../hooks/WindowDimensionsHook";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
entryTitle: {
|
||||
@@ -35,15 +36,18 @@ const useStyles = makeStyles(() => ({
|
||||
}));
|
||||
|
||||
export const formatSize = (n: number) => n > 1000 ? `${Math.round(n / 1000)}KB` : `${n} B`;
|
||||
|
||||
const minSizeDisplayRequestSize = 880;
|
||||
const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
||||
const classes = useStyles();
|
||||
const request = data.request;
|
||||
const response = data.response;
|
||||
|
||||
const { width } = useWindowDimensions();
|
||||
const {requestText, responseText, elapsedTimeText} = useRequestTextByWidth(width)
|
||||
|
||||
return <div className={classes.entryTitle}>
|
||||
<Protocol protocol={protocol} horizontal={true}/>
|
||||
<div style={{right: "30px", position: "absolute", display: "flex"}}>
|
||||
{(width > minSizeDisplayRequestSize) && <div style={{right: "30px", position: "absolute", display: "flex"}}>
|
||||
{request && <Queryable
|
||||
query={`requestSize == ${data.requestSize}`}
|
||||
style={{margin: "0 18px"}}
|
||||
@@ -53,7 +57,7 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
||||
style={{opacity: 0.5}}
|
||||
id="entryDetailedTitleRequestSize"
|
||||
>
|
||||
{`Request: ${formatSize(data.requestSize)}`}
|
||||
{`${requestText}${formatSize(data.requestSize)}`}
|
||||
</div>
|
||||
</Queryable>}
|
||||
{response && <Queryable
|
||||
@@ -65,22 +69,22 @@ const EntryTitle: React.FC<any> = ({protocol, data, elapsedTime}) => {
|
||||
style={{opacity: 0.5}}
|
||||
id="entryDetailedTitleResponseSize"
|
||||
>
|
||||
{`Response: ${formatSize(data.responseSize)}`}
|
||||
{`${responseText}${formatSize(data.responseSize)}`}
|
||||
</div>
|
||||
</Queryable>}
|
||||
{response && <Queryable
|
||||
query={`elapsedTime >= ${elapsedTime}`}
|
||||
style={{marginRight: 18}}
|
||||
style={{margin: "0 0 0 18px"}}
|
||||
displayIconOnMouseOver={true}
|
||||
>
|
||||
<div
|
||||
style={{opacity: 0.5}}
|
||||
id="entryDetailedTitleElapsedTime"
|
||||
>
|
||||
{`Elapsed Time: ${Math.round(elapsedTime)}ms`}
|
||||
{`${elapsedTimeText}${Math.round(elapsedTime)}ms`}
|
||||
</div>
|
||||
</Queryable>}
|
||||
</div>
|
||||
</div>}
|
||||
</div>;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,12 +48,13 @@ interface TrafficViewerProps {
|
||||
actionButtons?: JSX.Element,
|
||||
isShowStatusBar?: boolean,
|
||||
webSocketUrl : string,
|
||||
isCloseWebSocket : boolean
|
||||
isCloseWebSocket : boolean,
|
||||
isDemoBannerView : boolean
|
||||
}
|
||||
|
||||
export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus, trafficViewerApiProp,
|
||||
actionButtons,isShowStatusBar,webSocketUrl,
|
||||
isCloseWebSocket}) => {
|
||||
isCloseWebSocket, isDemoBannerView}) => {
|
||||
|
||||
const classes = useLayoutStyles();
|
||||
|
||||
@@ -293,7 +294,7 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
||||
|
||||
return (
|
||||
<div className={TrafficViewerStyles.TrafficPage}>
|
||||
{tappingStatus && isShowStatusBar && <StatusBar />}
|
||||
{tappingStatus && isShowStatusBar && <StatusBar isDemoBannerView={isDemoBannerView} />}
|
||||
<div className={TrafficViewerStyles.TrafficPageHeader}>
|
||||
<div className={TrafficViewerStyles.TrafficPageStreamStatus}>
|
||||
<img className={TrafficViewerStyles.playPauseIcon} style={{ visibility: ws?.current?.readyState === WebSocket.OPEN ? "visible" : "hidden" }} alt="pause"
|
||||
@@ -356,11 +357,11 @@ export const TrafficViewer : React.FC<TrafficViewerProps> = ({setAnalyzeStatus,
|
||||
const MemoiedTrafficViewer = React.memo(TrafficViewer)
|
||||
const TrafficViewerContainer: React.FC<TrafficViewerProps> = ({ setAnalyzeStatus, trafficViewerApiProp,
|
||||
actionButtons, isShowStatusBar = true ,
|
||||
webSocketUrl, isCloseWebSocket}) => {
|
||||
webSocketUrl, isCloseWebSocket, isDemoBannerView}) => {
|
||||
return <RecoilRoot>
|
||||
<MemoiedTrafficViewer actionButtons={actionButtons} isShowStatusBar={isShowStatusBar} webSocketUrl={webSocketUrl}
|
||||
isCloseWebSocket={isCloseWebSocket} trafficViewerApiProp={trafficViewerApiProp}
|
||||
setAnalyzeStatus={setAnalyzeStatus} />
|
||||
setAnalyzeStatus={setAnalyzeStatus} isDemoBannerView={isDemoBannerView} />
|
||||
</RecoilRoot>
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,16 @@ const pluralize = (noun: string, amount: number) => {
|
||||
return `${noun}${amount !== 1 ? 's' : ''}`
|
||||
}
|
||||
|
||||
export const StatusBar = () => {
|
||||
interface StatusBarProps {
|
||||
isDemoBannerView: boolean;
|
||||
}
|
||||
|
||||
export const StatusBar = ({isDemoBannerView}) => {
|
||||
const tappingStatus = useRecoilValue(tappingStatusAtom);
|
||||
const [expandedBar, setExpandedBar] = useState(false);
|
||||
const {uniqueNamespaces, amountOfPods, amountOfTappedPods, amountOfUntappedPods} = useRecoilValue(tappingStatusDetails);
|
||||
|
||||
return <div className={`${style.statusBar} ${(expandedBar ? `${style.expandedStatusBar}` : "")}`} onMouseOver={() => setExpandedBar(true)} onMouseLeave={() => setExpandedBar(false)} data-cy="expandedStatusBar">
|
||||
return <div className={`${isDemoBannerView ? `${style.banner}` : ''} ${style.statusBar} ${(expandedBar ? `${style.expandedStatusBar}` : "")}`} onMouseOver={() => setExpandedBar(true)} onMouseLeave={() => setExpandedBar(false)} data-cy="expandedStatusBar">
|
||||
<div className={style.podsCount}>
|
||||
{tappingStatus.some(pod => !pod.isTapped) && <img src={warningIcon} alt="warning"/>}
|
||||
<span className={style.podsCountText} data-cy="podsCountText">
|
||||
|
||||
@@ -9,4 +9,4 @@ import { InformationIcon } from "./InformationIcon";
|
||||
|
||||
|
||||
export {LoadingOverlay,Select,Tabs,Tooltip,Checkbox,CustomModal,InformationIcon}
|
||||
export {StatusBar}
|
||||
export {StatusBar}
|
||||
@@ -19,6 +19,9 @@
|
||||
overflow: hidden
|
||||
max-width: clamp(150px,50%,600px)
|
||||
|
||||
&.banner
|
||||
top: 53px
|
||||
|
||||
.podsCount
|
||||
display: flex
|
||||
justify-content: center
|
||||
|
||||
43
ui-common/src/hooks/WindowDimensionsHook.tsx
Normal file
43
ui-common/src/hooks/WindowDimensionsHook.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
function getWindowDimensions() {
|
||||
const { innerWidth: width, innerHeight: height } = window;
|
||||
return {
|
||||
width,
|
||||
height
|
||||
};
|
||||
}
|
||||
|
||||
export function useRequestTextByWidth(windowWidth){
|
||||
|
||||
let requestText = "Request: "
|
||||
let responseText = "Response: "
|
||||
let elapsedTimeText = "Elapsed Time: "
|
||||
|
||||
if (windowWidth < 1078) {
|
||||
requestText = ""
|
||||
responseText = ""
|
||||
elapsedTimeText = ""
|
||||
} else if (windowWidth < 1356) {
|
||||
requestText = "Req: "
|
||||
responseText = "Res: "
|
||||
elapsedTimeText = "ET: "
|
||||
}
|
||||
|
||||
return {requestText, responseText, elapsedTimeText}
|
||||
}
|
||||
|
||||
export default function useWindowDimensions() {
|
||||
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
|
||||
|
||||
useEffect(() => {
|
||||
function handleResize() {
|
||||
setWindowDimensions(getWindowDimensions());
|
||||
}
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
return () => window.removeEventListener('resize', handleResize);
|
||||
}, []);
|
||||
|
||||
return windowDimensions;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/node": "^12.20.10",
|
||||
"@uiw/react-textarea-code-editor": "^1.4.12",
|
||||
"@up9/mizu-common": "1.0.135",
|
||||
"@up9/mizu-common": "1.0.137",
|
||||
"axios": "^0.25.0",
|
||||
"core-js": "^3.20.2",
|
||||
"craco-babel-loader": "^1.0.3",
|
||||
|
||||
@@ -43,7 +43,7 @@ const trafficViewerApi = {...api}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||
style={{ marginRight: 25 }}
|
||||
style={{ marginRight: 25, textTransform: 'unset' }}
|
||||
onClick={handleOpenOasModal}>
|
||||
OpenApi Specs
|
||||
</Button>}
|
||||
@@ -52,7 +52,8 @@ const trafficViewerApi = {...api}
|
||||
size="large"
|
||||
variant="contained"
|
||||
className={commonClasses.outlinedButton + " " + commonClasses.imagedButton}
|
||||
onClick={openServiceMapModalDebounce}>
|
||||
onClick={openServiceMapModalDebounce}
|
||||
style={{textTransform: 'unset'}}>
|
||||
Service Map
|
||||
</Button>}
|
||||
</div>
|
||||
@@ -66,7 +67,7 @@ const trafficViewerApi = {...api}
|
||||
return (
|
||||
<>
|
||||
<TrafficViewer setAnalyzeStatus={setAnalyzeStatus} webSocketUrl={getWebsocketUrl()} isCloseWebSocket={!openWebSocket}
|
||||
trafficViewerApiProp={trafficViewerApi} actionButtons={actionButtons} isShowStatusBar={!openOasModal}/>
|
||||
trafficViewerApiProp={trafficViewerApi} actionButtons={actionButtons} isShowStatusBar={!openOasModal} isDemoBannerView={false}/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user