github.com/tigera/api@v0.0.0-20240320170621-278e89a8c5fb/pkg/apis/projectcalico/v3/reportdata.go (about)

     1  // Copyright (c) 2019 Tigera, Inc. All rights reserved.
     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 v3
    16  
    17  import (
    18  	"fmt"
    19  
    20  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    21  	"k8s.io/apiserver/pkg/apis/audit"
    22  )
    23  
    24  // ReportData contains the aggregated data available for rendering in report templates. The data available is dependent
    25  // on the selector/report configuration.
    26  //
    27  // The data is stored directly in elastic search. To reduce nesting and simplify indexing, all summary values are
    28  // contained at the top level.
    29  type ReportData struct {
    30  	ReportName     string         `json:"reportName"`
    31  	ReportTypeName string         `json:"reportTypeName"`
    32  	ReportSpec     ReportSpec     `json:"reportSpec"`
    33  	ReportTypeSpec ReportTypeSpec `json:"reportTypeSpec"`
    34  	StartTime      metav1.Time    `json:"startTime"`
    35  	EndTime        metav1.Time    `json:"endTime"`
    36  	GenerationTime metav1.Time    `json:"generationTime"`
    37  
    38  	// The set of in-scope endpoints.
    39  	Endpoints []EndpointsReportEndpoint `json:"endpoints,omitempty"`
    40  
    41  	// Endpoint stats in a reporting period.
    42  	EndpointsSummary EndpointsSummary `json:"endpointsSummary,omitempty"`
    43  
    44  	// The set of namespaces containing in-scope endpoints.
    45  	Namespaces []EndpointsReportNamespace `json:"namespaces,omitempty"`
    46  
    47  	// Endpoint stats for given namespaces in a reporting period.
    48  	NamespacesSummary EndpointsSummary `json:"namespacesSummary,omitempty"`
    49  
    50  	// The set of services containing in-scope endpoints.
    51  	Services []EndpointsReportService `json:"services,omitempty"`
    52  
    53  	// Endpoint stats for services in a reporting period.
    54  	ServicesSummary EndpointsSummary `json:"servicesSummary,omitempty"`
    55  
    56  	// The time-ordered set of in-scope audit events that occurred within the reporting interval.
    57  	AuditEvents []audit.Event `json:"auditEvents,omitempty"`
    58  
    59  	// Audit log stats in a reporting period.
    60  	AuditSummary AuditSummary `json:"auditSummary,omitempty"`
    61  
    62  	// Flows for in-scope endpoints that have been recorded within the reporting period.
    63  	Flows []EndpointsReportFlow `json:"flows,omitempty"`
    64  
    65  	// CISBenchmark contains the per-node results of a cis benchmark scan.
    66  	CISBenchmark []CISBenchmarkNode `json:"cisBenchmark,omitempty"`
    67  
    68  	// CISBenchmarkSummary high level test results.
    69  	CISBenchmarkSummary CISBenchmarkSummary `json:"cisBenchmarkSummary,omitempty"`
    70  }
    71  
    72  // This tracks different statistics for Endpoints, Summary and Services.
    73  type EndpointsSummary struct {
    74  	// For endpoints: the total number of in-scope endpoints.
    75  	//    Namespaces: the total number of namespaces containing in-scope endpoints.
    76  	//      Services: the total number of services containing in-scope endpoints.
    77  	//
    78  	// Source: Calculated from pod/wep, hep, namespace and service account labels.
    79  	NumTotal int `json:"numTotal,omitempty"`
    80  
    81  	// For endpoints: the total number of service accounts for in-scope endpoints.
    82  	//    Namespaces: n/a.
    83  	//      Services: n/a.
    84  	NumServiceAccounts int `json:"numServiceAccounts,omitempty"`
    85  
    86  	// For endpoints: the number of in-scope endpoints that were ingress protected during the reporting interval.
    87  	//    Namespaces: the number of namespaces whose in-scope endpoints were ingress protected during
    88  	//                the reporting interval.
    89  	//      Services: the number of services whose in-scope endpoints were ingress protected during the reporting
    90  	//                interval.
    91  	//
    92  	// See below for defn of ingress-protected.
    93  	NumIngressProtected int `json:"numIngressProtected,omitempty"`
    94  
    95  	// For endpoints: the number of in-scope endpoints that were egress protected during the reporting interval.
    96  	//    Namespaces: the number of namespaces whose in-scope endpoints were egress protected during the reporting
    97  	//                interval.
    98  	//
    99  	// See below for defn of egress-protected.
   100  	NumEgressProtected int `json:"numEgressProtected,omitempty"`
   101  
   102  	// For endpoints: the number of in-scope endpoints whose policy would allow ingress traffic from the Internet
   103  	//                for *any* period within the reporting interval.
   104  	//                (See below for how this is calculated for an endpoint.)
   105  	//    Namespaces: the number of namespaces that contained in-scope endpoints that would allow ingress traffic
   106  	//                from the Internet for *any* period within the reporting interval.
   107  	//      Services: the number of services that contained in-scope endpoints that would allow ingress traffic
   108  	//                from the Internet for *any* period within the reporting interval.
   109  	NumIngressFromInternet int `json:"numIngressFromInternet,omitempty"`
   110  
   111  	// For endpoints: the number of in-scope endpoints whose policy would allow egress traffic to the Internet
   112  	//                for *any* period within the reporting interval.
   113  	//                (See below for how this is calculated for an endpoint.)
   114  	//    Namespaces: the number of namespaces that contained in-scope endpoints that would allow egress traffic
   115  	//                to the Internet for *any* period within the reporting interval.
   116  	NumEgressToInternet int `json:"numEgressToInternet,omitempty"`
   117  
   118  	// For endpoints: the number of in-scope endpoints whose policy would allow ingress traffic from a
   119  	//                different namespace for *any* period within the reporting interval.
   120  	//                (See below for how this is calculated for an endpoint.)
   121  	//    Namespaces: the number of namespaces that contained in-scope endpoints that would allow ingress
   122  	//                traffic from another namespace for *any* period within the reporting interval.
   123  	//      Services: the number of services that contained in-scope endpoints that would allow ingress
   124  	//                traffic from another namespace for *any* period within the reporting interval.
   125  	NumIngressFromOtherNamespace int `json:"numIngressFromOtherNamespace,omitempty"`
   126  
   127  	// For endpoints: the number of in-scope endpoints whose policy would allow ingress traffic from
   128  	//                a different namespace for *any* period within the reporting interval.
   129  	//                (See below for how this is calculated for an endpoint.)
   130  	//    Namespaces: the number of namespaces that contained in-scope endpoints that would allow egress
   131  	//                traffic to another namespace for *any* period within the reporting interval.
   132  	NumEgressToOtherNamespace int `json:"numEgressToOtherNamespace,omitempty"`
   133  
   134  	// For endpoints: the number of in-scope endpoints that were envoy-enabled within the reporting interval.
   135  	//    Namespaces: the number of namespaces whose in-scope endpoints were always Envoy-enabled
   136  	//      Services: the number of services whose in-scope endpoints were always Envoy-enabled
   137  	//
   138  	// See below for defn of envoy-enabled
   139  	NumEnvoyEnabled int `json:"numEnvoyEnabled,omitempty"`
   140  }
   141  
   142  type AuditSummary struct {
   143  	// The total number of in-scope audit logs.
   144  	NumTotal int `json:"numTotal,omitempty"`
   145  
   146  	// The number of in-scope audit log create events.
   147  	NumCreate int `json:"numCreate,omitempty"`
   148  
   149  	// The number of in-scope audit log patch or replace events.
   150  	NumModify int `json:"numModify,omitempty"`
   151  
   152  	// The number of in-scope audit log delete events.
   153  	NumDelete int `json:"numDelete,omitempty"`
   154  }
   155  
   156  type EndpointsReportEndpoint struct {
   157  	Endpoint ResourceID `json:"endpoint,omitempty"`
   158  
   159  	// Whether ingress traffic to this endpoint was always protected during the reporting interval.
   160  	//
   161  	// Ingress protection is defined as denying ingress traffic unless explicitly whitelisted. This is translated as
   162  	// the endpoint having some explicit ingress policy applied to it.
   163  	//
   164  	// Source: Calculated from the set of ingress policies that apply to each endpoint.
   165  	//
   166  	// Set to:
   167  	// - false if there are no ingress policies applied to the endpoint at any point during the reporting interval.
   168  	// - true otherwise.
   169  	//
   170  	// Note: Policy is not inspected for protection bypass: for example match-all-and-allow rules which would effectively
   171  	//       short-circuit the default tier-drop behavior, in this case the match-all-and-allow would be considered to be
   172  	//       an explicit whitelist of all traffic. We could include simplistic all-match rules and check that they
   173  	//       don't result in an allow. To check for more circuitous match-all allows is much trickier (e.g. you have one
   174  	//       rule that allows for src!=1.2.3.0/24 and another rule that allows for src==1.2.3.0/24, which combined
   175  	//       is essentially an allow-all).
   176  	IngressProtected bool `json:"ingressProtected,omitempty"`
   177  
   178  	// Whether egress traffic to this endpoint was always protected during the reporting interval.
   179  	//
   180  	// Egress protection is defined as denying egress traffic unless explicitly whitelisted. This is translated as
   181  	// the endpoint having some explicit egress policy applied to it.
   182  	//
   183  	// Source: Calculated from the set of egress policies that apply to each endpoint.
   184  	//
   185  	// Set to:
   186  	// - false if there are no egress policies applied to the endpoint at any point during the reporting interval.
   187  	// - true otherwise.
   188  	//
   189  	// Note: Policy is not inspected for protection bypass: for example match-all-and-allow rules which would effectively
   190  	//       short-circuit the default tier-drop behavior, in this case the match-all-and-allow would be considered to be
   191  	//       an explicit whitelist of all traffic. We could include simplistic all-match rules and check that they
   192  	//       don't result in an allow. To check for more circuitous match-all allows is much trickier (e.g. you have one
   193  	//       rule that allows for src!=1.2.3.0/24 and another rule that allows for src==1.2.3.0/24, which combined
   194  	//       is essentially an allow-all). Similarly, policy that only contains pass rules would still count as being
   195  	//       protected.
   196  	EgressProtected bool `json:"egressProtected,omitempty"`
   197  
   198  	// Whether the matching policy has any ingress allow rules from a public IP address (as defined by the complement of
   199  	// the private addresses; private addresses default to those defined in RFC 1918, but may also be configured separately).
   200  	//
   201  	// Source: Calculated from the policies applied to the endpoint. The ingress allow rules in each policy are checked
   202  	//         to determine if any CIDR specified in the rule, either directly or through a matching network set, is an
   203  	//         internet address. Endpoint addresses are not included - therefore ingress from a pod that has a public
   204  	//         IP address will not be considered as “from internet”.
   205  	//
   206  	// Note: This is a simplification since it does not examine the policies to determine if it's actually possible to
   207  	//       hit one of these allow rules (e.g. a previous rule may be a match-all-deny).
   208  	IngressFromInternet bool `json:"ingressFromInternet,omitempty"`
   209  
   210  	// Whether the matching policy has any egress allow rules to a public IP address (as defined by the complement of
   211  	// the private addresses; private addresses default to those defined in RFC 1918, but may also be configured separately).
   212  	//
   213  	// Source: Calculated from the policies applied to the endpoint. The egress allow rules in each policy are checked
   214  	//         to determine if any CIDR specified in the rule, either directly or through a matching network set, is an
   215  	//         internet address. Endpoint addresses are not included - therefore egress to a pod that has a public
   216  	//         IP address will not be considered as “to internet”.
   217  	//
   218  	// Note 1: This is a simplification since it does not examine the policies to determine if it's actually possible to
   219  	//         hit one of these allow rules (e.g. a previous rule may be a match-all-deny).
   220  	EgressToInternet bool `json:"egressToInternet,omitempty"`
   221  
   222  	// Whether the matching policy has any ingress allow rules from another namespace.
   223  	//
   224  	// Source: Calculated from the policies applied to the endpoint.
   225  	//
   226  	// Set to true if:
   227  	// - this is a pod (i.e. namespaced) with an applied GlobalNetworkPolicy with an ingress allow rule with no CIDR match.
   228  	// - this is a pod with an applied NetworkPolicy with an ingress allow rule with a non-empty NamespaceSelector.
   229  	//
   230  	// Note: This is a simplification since it does not examine the policies to determine if it's actually possible to
   231  	//       hit one of these allow rules (e.g. a previous rule may be a match-all-deny, or endpoint selector may not
   232  	//       match any endpoints within the namespace).
   233  	IngressFromOtherNamespace bool `json:"ingressFromOtherNamespace,omitempty"`
   234  
   235  	// Whether the matching policy has any egress allow rules to another namespace.
   236  	//
   237  	// Source: Calculated from the policies applied to the endpoint.
   238  	//
   239  	// Set to true if:
   240  	// - this is a pod endpoint (i.e. namespaced) matches a GlobalNetworkPolicy with an egress allow rule with no CIDR match.
   241  	// - this is a pod endpoint which matches a NetworkPolicy with an egress allow rule with a non-empty NamespaceSelector.
   242  	//
   243  	// Note: This is a simplification since it does not examine the policies to determine if it's actually possible to
   244  	//       hit one of these allow rules (e.g. a previous rule may be a match-all-deny, or endpoint selector may not
   245  	//       match any endpoints within the namespace).
   246  	EgressToOtherNamespace bool `json:"egressToOtherNamespace,omitempty"`
   247  
   248  	// Whether this pod is envoy-enabled. This is simply an indicator of whether an Envoy container is running within the pod.
   249  	// Provided Istio is configured appropriately, this can provide a simplistic determination of whether the pod is mTLS
   250  	// enabled.
   251  	//
   252  	// Source: Pod spec.
   253  	//
   254  	// Set to:
   255  	// - true if envoy is running within the pod
   256  	// - false if envoy is not running within the pod
   257  	EnvoyEnabled bool `json:"envoyEnabled,omitempty"`
   258  
   259  	// The set of policies that apply to an endpoint may change within the reporting interval, this is the superset of all
   260  	// policies that applied to the endpoint during that interval.
   261  	AppliedPolicies []ResourceID `json:"appliedPolicies,omitempty"`
   262  
   263  	// The list of services that exposed this endpoint at any moment during the reporting interval.
   264  	//
   265  	// Source: Determined from the Kubernetes endpoints resource associated with the service.
   266  	Services []ResourceID `json:"services,omitempty"`
   267  
   268  	// The ServiceAccount configured on this endpoint.
   269  	ServiceAccount string `json:"serviceAccount,omitempty"`
   270  
   271  	// The flow log aggregation name. This is used to locate flow logs associated with this endpoint when flow log
   272  	// aggregation is turned on.
   273  	FlowLogAggregationName string `json:"flowLogAggregationName,omitempty"`
   274  }
   275  
   276  type EndpointsReportFlow struct {
   277  	// The source of the flow log.
   278  	Source FlowEndpoint `json:"source"`
   279  
   280  	// The destination of the flow log.
   281  	Destination FlowEndpoint `json:"destination"`
   282  }
   283  
   284  type FlowEndpoint struct {
   285  	// The endpoint type, indicating whether this is a Pod, HostEndpoint, NetworkSet, or internet.
   286  	Kind string `json:"kind"`
   287  
   288  	// The name of the endpoint. Note that this name may actually be a name prefix if flow logs have
   289  	// been aggregated.
   290  	Name string `json:"name"`
   291  
   292  	// Whether the name is an aggregation prefix rather than the actual name.
   293  	NameIsAggregationPrefix bool `json:"nameIsAggregationPrefix,omitempty"`
   294  
   295  	// The namespace of the endpoint.
   296  	Namespace string `json:"namespace,omitempty"`
   297  }
   298  
   299  type EndpointsReportNamespace struct {
   300  	Namespace ResourceID `json:"namespace,omitempty"`
   301  
   302  	// Whether ingress traffic was protected for all endpoints within this namespace within the reporting interval.
   303  	// This is a summary of information contained in the endpoints data.
   304  	IngressProtected bool `json:"ingressProtected,omitempty"`
   305  
   306  	// Whether egress traffic was protected for all endpoints within this namespace within the reporting interval.
   307  	// This is a summary of information contained in the endpoints data.
   308  	EgressProtected bool `json:"egressProtected,omitempty"`
   309  
   310  	// Whether ingress traffic was allowed from the internet for any endpoint within this namespace within the reporting
   311  	// interval.
   312  	IngressFromInternet bool `json:"ingressFromInternet,omitempty"`
   313  
   314  	// Whether ingress traffic was allowed from the internet for any endpoint within this namespace within the reporting
   315  	// interval.
   316  	EgressToInternet bool `json:"egressToInternet,omitempty"`
   317  
   318  	// Whether ingress traffic was allowed from another namespace for any endpoint within this namespace within the
   319  	// reporting interval.
   320  	IngressFromOtherNamespace bool `json:"ingressFromOtherNamespace,omitempty"`
   321  
   322  	// Whether ingress traffic was allowed from another namespace for any endpoint within this namespace within the
   323  	// reporting interval.
   324  	EgressToOtherNamespace bool `json:"egressToOtherNamespace,omitempty"`
   325  
   326  	// Whether envoy was enabled for all endpoints within this namespace within the reporting interval.
   327  	// This is a summary of information contained in the endpoints data.
   328  	EnvoyEnabled bool `json:"envoyEnabled,omitempty"`
   329  }
   330  
   331  type EndpointsReportService struct {
   332  	Service ResourceID `json:"service,omitempty"`
   333  
   334  	// Whether ingress traffic was protected for all endpoints within this namespace within the reporting interval.
   335  	// This is a summary of information contained in the endpoints data.
   336  	IngressProtected bool `json:"ingressProtected,omitempty"`
   337  
   338  	// Whether ingress traffic was allowed from the internet for any endpoint exposed by this service within the reporting
   339  	// interval.
   340  	IngressFromInternet bool `json:"ingressFromInternet,omitempty"`
   341  
   342  	// Whether ingress traffic was allowed from another namespace for any endpoint exposed by this service within the
   343  	// reporting interval.
   344  	IngressFromOtherNamespace bool `json:"ingressFromOtherNamespace,omitempty"`
   345  
   346  	// Whether envoy was enabled for all endpoints that were exposed by this service within the reporting interval.
   347  	// This is a summary of information contained in the endpoints data.
   348  	EnvoyEnabled bool `json:"envoyEnabled,omitempty"`
   349  }
   350  
   351  // Prints FlowEndpoint contents. This is a slightly less verbose version of the resource names but should have
   352  // sufficient context to be useful.
   353  func (f FlowEndpoint) String() string {
   354  	switch f.Kind {
   355  	case KindK8sPod:
   356  		// We add in the v1 version to be inline with the ResourceID printed format.
   357  		return fmt.Sprintf("%s.v1(%s/%s)", f.Kind, f.Namespace, f.Name)
   358  	case KindHostEndpoint, KindGlobalNetworkSet:
   359  		return fmt.Sprintf("%s(%s)", f.Kind, f.Name)
   360  	case KindFlowPublic, KindFlowPrivate:
   361  		return f.Kind
   362  	}
   363  	return fmt.Sprintf("%s(%s/%s)", f.Kind, f.Namespace, f.Name)
   364  }
   365  
   366  // CISBenchmarkSummary describes a CIS benchmarking result across an entire cluster.
   367  type CISBenchmarkSummary struct {
   368  	Type      string `json:"type"`
   369  	HighCount int    `json:"highCount"`
   370  	MedCount  int    `json:"medCount"`
   371  	LowCount  int    `json:"lowCount"`
   372  }
   373  
   374  // CISBenchmarkNode describes a CIS benchmarking result on a single node.
   375  type CISBenchmarkNode struct {
   376  	// NodeName is the name of the node the this set of benchmark results is from.
   377  	NodeName string `json:"nodeName"`
   378  
   379  	// KubernetesVersion is the version of the kubelet running on this node.
   380  	KubernetesVersion string `json:"kubernetesVersion"`
   381  
   382  	// BenchmarksVersion is the version of the benchmarks that ran on this node.
   383  	BenchmarksVersion string `json:"benchmarksVersion"`
   384  
   385  	// Summary is a set of summary stats for this set of node-specific benchmarks.
   386  	Summary CISBenchmarkNodeSummary `json:"summary"`
   387  
   388  	// Results is the detailed set of results for this set of node-specific benchmarks.
   389  	Results []CISBenchmarkSectionResult `json:"results"`
   390  }
   391  
   392  // CISBenchmarkNodeSummary keeps count of tests passed, failed, and marked as info on a single node.
   393  // Also has a status field to describe whether it is in HIGH, MED, or LOW status (based on [high|med]Threshold).
   394  type CISBenchmarkNodeSummary struct {
   395  	Status    string `json:"status"`
   396  	TotalPass int    `json:"totalPass"`
   397  	TotalFail int    `json:"totalFail"`
   398  	TotalInfo int    `json:"totalInfo"`
   399  	Total     int    `json:"total"`
   400  }
   401  
   402  // CISBenchmarkSectionResult describes the result of running the CIS benchmark on a single component.
   403  type CISBenchmarkSectionResult struct {
   404  	Status  string               `json:"status"`
   405  	Section string               `json:"section"`
   406  	Desc    string               `json:"desc"`
   407  	Pass    int                  `json:"pass"`
   408  	Fail    int                  `json:"fail"`
   409  	Info    int                  `json:"info"`
   410  	Results []CISBenchmarkResult `json:"results"`
   411  }
   412  
   413  // CISBenchmarkResult describes the result of a single CIS benchmark check.
   414  type CISBenchmarkResult struct {
   415  	TestNumber string `json:"testNumber"`
   416  	TestDesc   string `json:"testDesc"`
   417  	TestInfo   string `json:"testInfo"`
   418  	Status     string `json:"status"`
   419  	Scored     bool   `json:"scored"`
   420  }
   421  
   422  // CISBenchmarkResultCount keeps track of how many nodes had a certain test result.
   423  type CISBenchmarkResultCount struct {
   424  	CISBenchmarkResult
   425  	Count int `json:"count"`
   426  }