github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadget-collection/gadgets/trace/sni/gadget.go (about) 1 // Copyright 2019-2022 The Inspektor Gadget authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package snisnoop 16 17 import ( 18 "fmt" 19 20 "sigs.k8s.io/controller-runtime/pkg/client" 21 22 gadgetv1alpha1 "github.com/inspektor-gadget/inspektor-gadget/pkg/apis/gadget/v1alpha1" 23 "github.com/inspektor-gadget/inspektor-gadget/pkg/container-collection/networktracer" 24 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-collection/gadgets" 25 sniTracer "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/sni/tracer" 26 sniTypes "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/sni/types" 27 eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types" 28 ) 29 30 type Trace struct { 31 helpers gadgets.GadgetHelpers 32 client client.Client 33 34 started bool 35 36 tracer *sniTracer.Tracer 37 conn *networktracer.ConnectionToContainerCollection 38 } 39 40 type TraceFactory struct { 41 gadgets.BaseFactory 42 } 43 44 func NewFactory() gadgets.TraceFactory { 45 return &TraceFactory{ 46 BaseFactory: gadgets.BaseFactory{DeleteTrace: deleteTrace}, 47 } 48 } 49 50 func (f *TraceFactory) Description() string { 51 return `The snisnoop gadget retrieves Server Name Indication (SNI) from TLS requests.` 52 } 53 54 func (f *TraceFactory) OutputModesSupported() map[gadgetv1alpha1.TraceOutputMode]struct{} { 55 return map[gadgetv1alpha1.TraceOutputMode]struct{}{ 56 gadgetv1alpha1.TraceOutputModeStream: {}, 57 } 58 } 59 60 func deleteTrace(name string, t interface{}) { 61 trace := t.(*Trace) 62 if trace.started { 63 if trace.conn != nil { 64 trace.conn.Close() 65 } 66 trace.tracer.Close() 67 trace.tracer = nil 68 } 69 } 70 71 func (f *TraceFactory) Operations() map[gadgetv1alpha1.Operation]gadgets.TraceOperation { 72 n := func() interface{} { 73 return &Trace{ 74 client: f.Client, 75 helpers: f.Helpers, 76 } 77 } 78 79 return map[gadgetv1alpha1.Operation]gadgets.TraceOperation{ 80 gadgetv1alpha1.OperationStart: { 81 Doc: "Start snisnoop", 82 Operation: func(name string, trace *gadgetv1alpha1.Trace) { 83 f.LookupOrCreate(name, n).(*Trace).Start(trace) 84 }, 85 }, 86 gadgetv1alpha1.OperationStop: { 87 Doc: "Stop snisnoop", 88 Operation: func(name string, trace *gadgetv1alpha1.Trace) { 89 f.LookupOrCreate(name, n).(*Trace).Stop(trace) 90 }, 91 }, 92 } 93 } 94 95 func (t *Trace) publishEvent(trace *gadgetv1alpha1.Trace, event *sniTypes.Event) { 96 traceName := gadgets.TraceName(trace.ObjectMeta.Namespace, trace.ObjectMeta.Name) 97 t.helpers.PublishEvent( 98 traceName, 99 eventtypes.EventString(event), 100 ) 101 } 102 103 func (t *Trace) Start(trace *gadgetv1alpha1.Trace) { 104 if t.started { 105 trace.Status.State = gadgetv1alpha1.TraceStateStarted 106 return 107 } 108 109 eventCallback := func(event *sniTypes.Event) { 110 t.publishEvent(trace, event) 111 } 112 113 var err error 114 t.tracer, err = sniTracer.NewTracer() 115 if err != nil { 116 trace.Status.OperationError = fmt.Sprintf("Failed to start sni tracer: %s", err) 117 return 118 } 119 t.tracer.SetEventHandler(eventCallback) 120 121 config := &networktracer.ConnectToContainerCollectionConfig[sniTypes.Event]{ 122 Tracer: t.tracer, 123 Resolver: t.helpers, 124 Selector: *gadgets.ContainerSelectorFromContainerFilter(trace.Spec.Filter), 125 Base: sniTypes.Base, 126 } 127 t.conn, err = networktracer.ConnectToContainerCollection(config) 128 if err != nil { 129 trace.Status.OperationError = fmt.Sprintf("Failed to start sni tracer: %s", err) 130 return 131 } 132 133 if err := t.tracer.RunWorkaround(); err != nil { 134 trace.Status.OperationError = fmt.Sprintf("Failed to start sni tracer: %s", err) 135 return 136 } 137 138 t.started = true 139 140 trace.Status.State = gadgetv1alpha1.TraceStateStarted 141 } 142 143 func (t *Trace) Stop(trace *gadgetv1alpha1.Trace) { 144 if !t.started { 145 trace.Status.OperationError = "Not started" 146 return 147 } 148 149 if t.conn != nil { 150 t.conn.Close() 151 } 152 t.tracer.Close() 153 t.tracer = nil 154 t.started = false 155 156 trace.Status.State = gadgetv1alpha1.TraceStateStopped 157 }