Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrating the Reports API from Kubernetes working group #2

Merged
merged 2 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module sigs.k8s.io/wg-policy-prototypes

go 1.22.0

toolchain go1.22.1

require (
k8s.io/api v0.29.3
k8s.io/apimachinery v0.30.0-rc.2
k8s.io/client-go v0.29.3
k8s.io/code-generator v0.30.0-rc.2
sigs.k8s.io/controller-runtime v0.16.3
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.14.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.20.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
185 changes: 185 additions & 0 deletions go.sum

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions policy-report/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Kubernetes Generated files - skip generated files, except for vendored files

!vendor/**/zz_generated.*

# editor and IDE paraphernalia
.idea
*.swp
*.swo
*~
94 changes: 94 additions & 0 deletions policy-report/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
GO_CMD ?= go

PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)

CONTROLLER_TOOLS_VERSION ?= v0.14.0
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
GEN_CRD_API_REFERENCE_DOCS ?= $(LOCALBIN)/crd-ref-docs
GEN_CRD_API_REFERENCE_DOCS_VERSION ?= latest

all: manifests generate generate-api-docs generate-client build fmt vet

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./apis/reports.x-k8s.io/v1beta2" output:crd:artifacts:config=crd/reports.x-k8s.io/v1beta2

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./apis/..."

.PHONY: generate-client
generate-client:
./hack/update-codegen.sh


# Run go build against code
build:
go build ./...

# Run go fmt against code
fmt:
go fmt ./...

# Run go vet against code
vet:
go vet ./...

.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten.
$(CONTROLLER_GEN): $(LOCALBIN)
test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
GOBIN=$(LOCALBIN) $(GO_CMD) install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)

# Use same code-generator version as k8s.io/api
CODEGEN_VERSION := v0.30.0-rc.2
CODEGEN = $(shell pwd)/bin/code-generator
CODEGEN_ROOT = $(shell $(GO_CMD) env GOMODCACHE)/k8s.io/code-generator@$(CODEGEN_VERSION)
.PHONY: code-generator
code-generator:
@GOBIN=$(PROJECT_DIR)/bin GO111MODULE=on $(GO_CMD) install k8s.io/code-generator/cmd/client-gen@$(CODEGEN_VERSION)
cp -f $(CODEGEN_ROOT)/generate-groups.sh $(PROJECT_DIR)/bin/
cp -f $(CODEGEN_ROOT)/generate-internal-groups.sh $(PROJECT_DIR)/bin/
cp -f $(CODEGEN_ROOT)/kube_codegen.sh $(PROJECT_DIR)/bin/

# generate-api-docs will create api docs
generate-api-docs: $(GEN_CRD_API_REFERENCE_DOCS)
$(GEN_CRD_API_REFERENCE_DOCS) --source-path=./apis/reports.x-k8s.io/v1beta2 --config=./docs/config.yaml --renderer=markdown --output-path=./docs/api-docs.md

$(GEN_CRD_API_REFERENCE_DOCS): $(LOCALBIN)
$(call go-install-tool,$(GEN_CRD_API_REFERENCE_DOCS),github.com/elastic/crd-ref-docs,$(GEN_CRD_API_REFERENCE_DOCS_VERSION))

.PHONY: codegen-api-docs
codegen-api-docs: $(PACKAGE_SHIM) $(GEN_CRD_API_REFERENCE_DOCS) $(GENREF) ## Generate API docs
@echo Generate api docs... >&2
$(GEN_CRD_API_REFERENCE_DOCS) -v=4 \
-api-dir pkg/api \
-config docs/config.json \
-template-dir docs/template \
-out-file docs/index.html

# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary (ideally with version)
# $2 - package url which can be installed
# $3 - specific version of package
define go-install-tool
@[ -f $(1) ] || { \
set -e; \
package=$(2)@$(3) ;\
echo "Downloading $${package}" ;\
GOBIN=$(LOCALBIN) go install $${package} ;\
mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
}
endef
84 changes: 84 additions & 0 deletions policy-report/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Report API

The Report API enables uniform reporting of results and findings from policy engines, scanners, or other tooling.

This repository contains the API specification and Custom Resource Definitions (CRDs).

## Concepts

The API provides a `ClusterReport` and its namespaced variant `Report`.

Each `Report` contains a set of `results` and a `summary`. Each `result` contains attributes such as the source policy and rule name, severity, timestamp, and the resource.

## Reference

* [API Reference](./docs/api-docs.md)

## Demonstration

Typically the Report API is installed and managed by a [producer](#producers). However, to try out the API in a test cluster you can follow the steps below:

1. Add Report API CRDs to your cluster (v1beta2):

```sh
kubectl create -f crd/reports.x-k8s.io/v1beta2/
```
2. Create a sample policy report resource:

```sh
kubectl create -f samples/sample-cis-k8s.yaml
```
3. View policy report resources:

```sh
kubectl get reports
```

## Implementations

The following is a list of projects that produce or consume policy reports:

*(To add your project, please create a [pull request](https://github.com/kubernetes-sigs/wg-policy-prototypes/pulls).)*

### Producers

* [Falco](https://github.com/falcosecurity/falcosidekick/blob/master/outputs/policyreport.go)
* [Image Scanner](https://github.com/statnett/image-scanner-operator)
* [jsPolicy](https://github.com/loft-sh/jspolicy/)
* [Kyverno](https://kyverno.io/docs/policy-reports/)
* [Netchecks](https://docs.netchecks.io/)
* [Tracee Adapter](https://github.com/fjogeleit/tracee-polr-adapter)
* [Trivy Operator](https://aquasecurity.github.io/trivy-operator/v0.15.1/tutorials/integrations/policy-reporter/)
* [Kubewarden](https://docs.kubewarden.io/explanations/audit-scanner/policy-reports)

### Consumers

* [Fairwinds Insights](https://fairwinds.com/insights)
* [Kyverno Policy Reporter](https://kyverno.github.io/policy-reporter/)
* [Open Cluster Management](https://open-cluster-management.io/)

## Building

```sh
make all
```

## Community, discussion, contribution, and support

You can reach the maintainers of this project at:

- [Slack](https://kubernetes.slack.com/messages/wg-policy)
- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-wg-policy)
- [WG Policy](https://github.com/kubernetes/community/blob/master/wg-policy/README.md)

### Code of conduct

Participation in the OpenReport community is governed by the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md).

[owners]: https://git.k8s.io/community/contributors/guide/owners.md
[Creative Commons 4.0]: https://git.k8s.io/website/LICENSE

# Historical References

See the [Kubernetes policy working group](https://github.com/kubernetes-sigs/wg-policy-prototypes/tree/master) and the [proposal](https://docs.google.com/document/d/1nICYLkYS1RE3gJzuHOfHeAC25QIkFZfgymFjgOzMDVw/edit#) for background and details.

Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
Copyright 2024 The Kubernetes authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1beta2

import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +genclient:nonNamespaced
// +kubebuilder:storageversion
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=clusterreports,scope="Cluster",shortName=creps
// +kubebuilder:printcolumn:name="Kind",type=string,JSONPath=`.scope.kind`,priority=1
// +kubebuilder:printcolumn:name="Name",type=string,JSONPath=`.scope.name`,priority=1
// +kubebuilder:printcolumn:name="Pass",type=integer,JSONPath=`.summary.pass`
// +kubebuilder:printcolumn:name="Fail",type=integer,JSONPath=`.summary.fail`
// +kubebuilder:printcolumn:name="Warn",type=integer,JSONPath=`.summary.warn`
// +kubebuilder:printcolumn:name="Error",type=integer,JSONPath=`.summary.error`
// +kubebuilder:printcolumn:name="Skip",type=integer,JSONPath=`.summary.skip`
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"

// ClusterReport is the Schema for the clusterpolicyreports API
type ClusterReport struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// Source is an identifier for the source e.g. a policy engine that manages this report.
// Use this field if all the results are produced by a single policy engine.
// If the results are produced by multiple sources e.g. different engines or scanners,
// then use the Source field at the ReportResult level.
// +optional
Source string `json:"source"`

// Scope is an optional reference to the report scope (e.g. a Deployment, Namespace, or Node)
// +optional
Scope *corev1.ObjectReference `json:"scope,omitempty"`

// ScopeSelector is an optional selector for multiple scopes (e.g. Pods).
// Either one of, or none of, but not both of, Scope or ScopeSelector should be specified.
// +optional
ScopeSelector *metav1.LabelSelector `json:"scopeSelector,omitempty"`

// Configuration is an optional field which can be used to specify
// a contract between Report generators and consumers
// +optional
Configuration *ReportConfiguration `json:"configuration,omitempty"`

// ReportSummary provides a summary of results
// +optional
Summary ReportSummary `json:"summary,omitempty"`

// ReportResult provides result details
// +optional
Results []ReportResult `json:"results,omitempty"`
}

// ClusterReportList contains a list of ClusterReport
// +kubebuilder:object:root=true
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ClusterReportList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ClusterReport `json:"items"`
}

func init() {
SchemeBuilder.Register(&ClusterReport{}, &ClusterReportList{})
}
22 changes: 22 additions & 0 deletions policy-report/apis/reports.x-k8s.io/v1beta2/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Copyright 2024 The Kubernetes authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package v1beta2 contains API Schema definitions for the policy v1beta2 API group
// +k8s:deepcopy-gen=package
// +kubebuilder:object:generate=true
// +k8s:openapi-gen=true
// +groupName=reports.x-k8s.io
package v1beta2
Loading