44package policyfilter
55
66import (
7+ "context"
78 "fmt"
9+ "os"
10+ "path"
811 "path/filepath"
912 "strconv"
13+ "strings"
14+ "text/tabwriter"
1015
16+ "github.com/cilium/tetragon/api/v1/tetragon"
17+ "github.com/cilium/tetragon/cmd/tetra/common"
1118 "github.com/cilium/tetragon/cmd/tetra/debug"
1219 "github.com/cilium/tetragon/pkg/cgroups"
20+ "github.com/cilium/tetragon/pkg/cri"
1321 "github.com/cilium/tetragon/pkg/defaults"
1422 "github.com/cilium/tetragon/pkg/logger"
1523 "github.com/cilium/tetragon/pkg/policyfilter"
@@ -29,6 +37,7 @@ func New() *cobra.Command {
2937 addCommand (),
3038 cgroupGetIDCommand (),
3139 dumpDebugCmd (),
40+ listPoliciesForContainer (),
3241 )
3342
3443 return ret
@@ -138,3 +147,133 @@ func addCgroup(fname string, polID policyfilter.PolicyID, cgID policyfilter.Cgro
138147 }
139148
140149}
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