4
4
package policyfilter
5
5
6
6
import (
7
+ "context"
7
8
"fmt"
9
+ "os"
10
+ "path"
8
11
"path/filepath"
9
12
"strconv"
13
+ "strings"
14
+ "text/tabwriter"
10
15
16
+ "github.com/cilium/tetragon/api/v1/tetragon"
17
+ "github.com/cilium/tetragon/cmd/tetra/common"
11
18
"github.com/cilium/tetragon/cmd/tetra/debug"
12
19
"github.com/cilium/tetragon/pkg/cgroups"
20
+ "github.com/cilium/tetragon/pkg/cri"
13
21
"github.com/cilium/tetragon/pkg/defaults"
14
22
"github.com/cilium/tetragon/pkg/logger"
15
23
"github.com/cilium/tetragon/pkg/policyfilter"
@@ -29,6 +37,7 @@ func New() *cobra.Command {
29
37
addCommand (),
30
38
cgroupGetIDCommand (),
31
39
dumpDebugCmd (),
40
+ listPoliciesForContainer (),
32
41
)
33
42
34
43
return ret
@@ -138,3 +147,133 @@ func addCgroup(fname string, polID policyfilter.PolicyID, cgID policyfilter.Cgro
138
147
}
139
148
140
149
}
150
+
151
+ func listPoliciesForContainer () * cobra.Command {
152
+ var endpoint , cgroupMnt string
153
+ mapFname := filepath .Join (defaults .DefaultMapRoot , defaults .DefaultMapPrefix , policyfilter .MapName )
154
+ ret := & cobra.Command {
155
+ Use : "listpolicies [container id]" ,
156
+ Short : "list all Kubernetes Identity Aware policies that apply to a specific container" ,
157
+ Args : cobra .ExactArgs (1 ),
158
+ RunE : func (_ * cobra.Command , args []string ) error {
159
+ ctx := context .Background ()
160
+ client , err := cri .NewClient (ctx , endpoint )
161
+ if err != nil {
162
+ return err
163
+ }
164
+
165
+ cgroupPath , err := cri .CgroupPath (ctx , client , args [0 ])
166
+ if err != nil {
167
+ return err
168
+ }
169
+
170
+ fmt .Printf ("cgroupPath [%s]\n " , cgroupPath )
171
+ fmt .Printf ("defaults.Cgroup2Dir [%s]\n " , defaults .Cgroup2Dir )
172
+ fmt .Printf ("cgroupMnt [%s]\n " , cgroupMnt )
173
+
174
+ if cgroupMnt == "" {
175
+ cgroupMnt = defaults .Cgroup2Dir
176
+ }
177
+ fullCgroupPath := path .Join (cgroupMnt , cgroupPath )
178
+ fmt .Printf ("fullCgroupPath [%s]\n " , fullCgroupPath )
179
+
180
+ cgID , err := cgroups .GetCgroupIdFromPath (fullCgroupPath )
181
+ if err != nil {
182
+ logger .GetLogger ().WithError (err ).Fatal ("Failed to parse cgroup" )
183
+ }
184
+
185
+ fmt .Printf ("cgroupId [%d]\n " , cgID )
186
+
187
+ m , err := policyfilter .OpenMap (mapFname )
188
+ if err != nil {
189
+ logger .GetLogger ().WithError (err ).Fatal ("Failed to open policyfilter map" )
190
+ return err
191
+ }
192
+ defer m .Close ()
193
+
194
+ data , err := m .Dump ()
195
+ if err != nil {
196
+ logger .GetLogger ().WithError (err ).Fatal ("Failed to open policyfilter map" )
197
+ return err
198
+ }
199
+
200
+ policyIds , ok := data .Reverse [policyfilter .CgroupID (cgID )]
201
+ if ! ok {
202
+ return nil
203
+ }
204
+
205
+ fmt .Println ("policyIds" , policyIds )
206
+
207
+ c , err := common .NewClientWithDefaultContextAndAddress ()
208
+ if err != nil {
209
+ return fmt .Errorf ("failed create gRPC client: %w" , err )
210
+ }
211
+ defer c .Close ()
212
+
213
+ res , err := c .Client .ListTracingPolicies (c .Ctx , & tetragon.ListTracingPoliciesRequest {})
214
+ if err != nil || res == nil {
215
+ return fmt .Errorf ("failed to list tracing policies: %w" , err )
216
+ }
217
+
218
+ // tabwriter config imitates kubectl default output, i.e. 3 spaces padding
219
+ w := tabwriter .NewWriter (os .Stdout , 0 , 0 , 3 , ' ' , 0 )
220
+ fmt .Fprintln (w , "ID\t NAME\t STATE\t FILTERID\t NAMESPACE\t SENSORS\t KERNELMEMORY" )
221
+
222
+ for _ , pol := range res .Policies {
223
+ namespace := pol .Namespace
224
+ if namespace == "" {
225
+ namespace = "(global)"
226
+ }
227
+
228
+ sensors := strings .Join (pol .Sensors , "," )
229
+
230
+ // From v0.11 and before, enabled, filterID and error were
231
+ // bundled in a string. To have a retro-compatible tetra
232
+ // command, we scan the string. If the scan fails, it means
233
+ // something else might be in Info and we print it.
234
+ //
235
+ // we can drop the following block (and comment) when we
236
+ // feel tetra should support only version after v0.11
237
+ if pol .Info != "" {
238
+ var parsedEnabled bool
239
+ var parsedFilterID uint64
240
+ var parsedError string
241
+ var parsedName string
242
+ str := strings .NewReader (pol .Info )
243
+ _ , err := fmt .Fscanf (str , "%253s enabled:%t filterID:%d error:%512s" , & parsedName , & parsedEnabled , & parsedFilterID , & parsedError )
244
+ if err == nil {
245
+ if parsedEnabled {
246
+ pol .State = tetragon .TracingPolicyState_TP_STATE_ENABLED
247
+ }
248
+ pol .FilterId = parsedFilterID
249
+ pol .Error = parsedError
250
+ pol .Info = ""
251
+ }
252
+ }
253
+
254
+ if _ , ok := policyIds [policyfilter .PolicyID (pol .FilterId )]; ! ok {
255
+ continue
256
+ }
257
+
258
+ fmt .Fprintf (w , "%d\t %s\t %s\t %d\t %s\t %s\t %s\t \n " ,
259
+ pol .Id ,
260
+ pol .Name ,
261
+ strings .TrimPrefix (strings .ToLower (pol .State .String ()), "tp_state_" ),
262
+ pol .FilterId ,
263
+ namespace ,
264
+ sensors ,
265
+ common .HumanizeByteCount (int (pol .KernelMemoryBytes )),
266
+ )
267
+ }
268
+ w .Flush ()
269
+
270
+ return nil
271
+ },
272
+ }
273
+
274
+ flags := ret .Flags ()
275
+ flags .StringVarP (& endpoint , "runtime-endpoint" , "r" , "" , "CRI endpoint" )
276
+ flags .StringVar (& mapFname , "map-fname" , mapFname , "policyfilter map filename" )
277
+ flags .StringVar (& cgroupMnt , "cgroup-mount" , cgroupMnt , "cgroupFS mount point" )
278
+ return ret
279
+ }
0 commit comments