diff --git a/Makefile b/Makefile index 28bd7fb..7a6a331 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,25 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BIN_DIR := $(abspath $(ROOT_DIR)/bin) - GOLANGCI_LINT_VER := v1.59.1 GOLANGCI_LINT_BIN := golangci-lint GOLANGCI_LINT := $(BIN_DIR)/$(GOLANGCI_LINT_BIN) +# Run go fmt against code +fmt: + go fmt ./... + +# Run go vet against code +vet: + go vet ./... + +deps: + go get github.com/golangci/golangci-lint/cmd/golangci-lint + go install github.com/vektra/mockery/v2@v2.43.2 + +generate-mocks: + mockery + golangci-lint: $(GOLANGCI_LINT) ## Install a local copy of golang ci-lint. $(GOLANGCI_LINT): ## Install golangci-lint. GOBIN=$(BIN_DIR) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VER) @@ -23,17 +37,3 @@ lint-fix: $(GOLANGCI_LINT) test: fmt vet go test ./... -coverprofile cover.out -# Run go fmt against code -fmt: - go fmt ./... - -# Run go vet against code -vet: - go vet ./... - -deps: - go get github.com/golangci/golangci-lint/cmd/golangci-lint - go install github.com/vektra/mockery/v2@v2.43.2 - -generate-mocks: - mockery diff --git a/constants/constants.go b/constants/constants.go index 3e4a6b5..6108a67 100644 --- a/constants/constants.go +++ b/constants/constants.go @@ -2,7 +2,7 @@ package constants const ( // ProtocolVersion is the version of the protocol used by the - // Kubewarden waPC host and guest to exchange information + // Kubewarden waPC host and guest to exchange information. ProtocolVersion = "v1" // These two media types are manifests media types that the // oci-distribution accepts when fetching images manifests. But they diff --git a/kubewarden.go b/kubewarden.go index f66a673..bf9adcb 100644 --- a/kubewarden.go +++ b/kubewarden.go @@ -13,24 +13,24 @@ import ( "github.com/kubewarden/policy-sdk-go/protocol" ) -// Message is the optional string used to build validation responses +// Message is the optional string used to build validation responses. type Message string -// Code is the optional error code associated with validation responses +// Code is the optional error code associated with validation responses. type Code uint16 const ( // NoMessage can be used when building a response that doesn't have any - // message to be shown to the user + // message to be shown to the user. NoMessage Message = "" // NoCode can be used when building a response that doesn't have any - // error code to be shown to the user + // error code to be shown to the user. NoCode Code = 0 ) // AcceptRequest can be used inside of the `validate` function to accept the -// incoming request +// incoming request. func AcceptRequest() ([]byte, error) { response := protocol.ValidationResponse{ Accepted: true, @@ -42,7 +42,7 @@ func AcceptRequest() ([]byte, error) { // RejectRequest can be used inside of the `validate` function to reject the // incoming request // * `message`: optional message to show to the user -// * `code`: optional error code to show to the user +// * `code`: optional error code to show to the user. func RejectRequest(message Message, code Code) ([]byte, error) { response := protocol.ValidationResponse{ Accepted: false, @@ -60,7 +60,7 @@ func RejectRequest(message Message, code Code) ([]byte, error) { } // Accept the request and mutate the final object to match the -// one provided via the `newObject` param +// one provided via the `newObject` param. func MutateRequest(newObject interface{}) ([]byte, error) { response := protocol.ValidationResponse{ Accepted: true, @@ -73,7 +73,9 @@ func MutateRequest(newObject interface{}) ([]byte, error) { // Update the pod spec from the resource defined in the original object and // create an acceptance response. // * `validation_request` - the original admission request -// * `pod_spec` - new PodSpec to be set in the response +// * `pod_spec` - new PodSpec to be set in the response. +// +//nolint:funlen // Splitting this function would not make it more readable. func MutatePodSpecFromRequest(validationRequest protocol.ValidationRequest, podSepc corev1.PodSpec) ([]byte, error) { switch validationRequest.Request.Kind.Kind { case "Deployment": @@ -133,12 +135,13 @@ func MutatePodSpecFromRequest(validationRequest protocol.ValidationRequest, podS pod.Spec = &podSepc return MutateRequest(pod) default: - return RejectRequest("Object should be one of these kinds: Deployment, ReplicaSet, StatefulSet, DaemonSet, ReplicationController, Job, CronJob, Pod", NoCode) + return RejectRequest("Object should be one of these kinds: Deployment, "+ + "ReplicaSet, StatefulSet, DaemonSet, ReplicationController, Job, CronJob, Pod", NoCode) } } // AcceptSettings can be used inside of the `validate_settings` function to -// mark the user provided settings as valid +// mark the user provided settings as valid. func AcceptSettings() ([]byte, error) { response := protocol.SettingsValidationResponse{ Valid: true, @@ -148,7 +151,7 @@ func AcceptSettings() ([]byte, error) { // RejectSettings can be used inside of the `validate_settings` function to // mark the user provided settings as invalid -// * `message`: optional message to show to the user +// * `message`: optional message to show to the user. func RejectSettings(message Message) ([]byte, error) { response := protocol.SettingsValidationResponse{ Valid: false, @@ -168,7 +171,7 @@ func RejectSettings(message Message) ([]byte, error) { // DaemonSet, ReplicationController, Job, CronJob, Pod It returns an error if // the object is not one of those. If it is a supported object it returns the // PodSpec if present, otherwise returns an empty PodSpec. -// * `object`: the request to validate +// * `object`: the request to validate. func ExtractPodSpecFromObject(object protocol.ValidationRequest) (corev1.PodSpec, error) { switch object.Request.Kind.Kind { case "Deployment": @@ -220,6 +223,7 @@ func ExtractPodSpecFromObject(object protocol.ValidationRequest) (corev1.PodSpec } return *pod.Spec, nil default: - return corev1.PodSpec{}, errors.New("object should be one of these kinds: Deployment, ReplicaSet, StatefulSet, DaemonSet, ReplicationController, Job, CronJob, Pod") + return corev1.PodSpec{}, errors.New("object should be one of these kinds: " + + "Deployment, ReplicaSet, StatefulSet, DaemonSet, ReplicationController, Job, CronJob, Pod") } } diff --git a/kubewarden_test.go b/kubewarden_test.go index 199c238..bea0bcf 100644 --- a/kubewarden_test.go +++ b/kubewarden_test.go @@ -2,7 +2,7 @@ package sdk import ( "encoding/json" - "fmt" + "errors" "testing" appsv1 "github.com/kubewarden/k8s-objects/api/apps/v1" @@ -49,11 +49,11 @@ func CheckIfAutomountServiceAccountTokenIsTrue(rawResponse []byte, mutatedObject } if !response.Accepted { - return fmt.Errorf("Response not accepted") + return errors.New("Response not accepted") } if response.MutatedObject == nil { - return fmt.Errorf("Request not mutated") + return errors.New("Request not mutated") } return nil @@ -198,7 +198,7 @@ func TestMutatePodSpecFromRequest(t *testing.T) { t.Fatalf("Error: %v", err) } - if err := CheckIfAutomountServiceAccountTokenIsTrue(rawResponse, testCase.mutatedObject); err != nil { + if err = CheckIfAutomountServiceAccountTokenIsTrue(rawResponse, testCase.mutatedObject); err != nil { t.Fatalf("Error: %v", err) } @@ -258,7 +258,7 @@ func TestMutatePodSpecFromRequestWithInvalidResourceType(t *testing.T) { } response := protocol.ValidationResponse{} - if err := json.Unmarshal(rawResponse, &response); err != nil { + if err = json.Unmarshal(rawResponse, &response); err != nil { t.Fatalf("Error: %v", err) } diff --git a/log_writer_native.go b/log_writer_native.go index 8326e1e..0e7803b 100644 --- a/log_writer_native.go +++ b/log_writer_native.go @@ -10,9 +10,10 @@ import ( "fmt" ) -func (k *KubewardenLogWriter) Write(p []byte) (n int, err error) { - n, err = k.buffer.Write(p) +func (k *KubewardenLogWriter) Write(p []byte) (int, error) { + n, err := k.buffer.Write(p) line, _ := k.buffer.ReadBytes('\n') + //nolint:forbidigo // this is a debug print fmt.Printf("NATIVE: |%s|\n", string(line)) - return + return n, err } diff --git a/pkg/capabilities/crypto/crypto.go b/pkg/capabilities/crypto/crypto.go index bd16661..b8f40fa 100644 --- a/pkg/capabilities/crypto/crypto.go +++ b/pkg/capabilities/crypto/crypto.go @@ -2,16 +2,17 @@ package crypto import ( "encoding/json" + "errors" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) type CryptoHost struct { - cap.Host + capabilities.Host } -// The encoding of the certificate +// The encoding of the certificate. type CertificateEncoding int const ( @@ -26,7 +27,7 @@ func (e CertificateEncoding) MarshalJSON() ([]byte, error) { return json.Marshal("Pem") } - return nil, fmt.Errorf("invalid certificate encoding") + return nil, errors.New("invalid certificate encoding") } // Verify_cert verifies cert's trust against the passed cert_chain, and @@ -37,7 +38,7 @@ func (e CertificateEncoding) MarshalJSON() ([]byte, error) { // (intermediates first, root last). If empty, certificate is assumed trusted. // - not_after: string in RFC 3339 time format, to check expiration against. // If None, certificate is assumed never expired. -func VerifyCert(h *cap.Host, cert Certificate, certChain []Certificate, notAfter string) (*CertificateVerificationResponse, error) { +func VerifyCert(h *capabilities.Host, cert Certificate, certChain []Certificate, notAfter string) (*CertificateVerificationResponse, error) { requestObj := CertificateVerificationRequest{ Cert: cert, CertChain: certChain, @@ -56,7 +57,7 @@ func VerifyCert(h *cap.Host, cert Certificate, certChain []Certificate, notAfter } responseObj := CertificateVerificationResponse{} - if err := json.Unmarshal(responsePayload, &responseObj); err != nil { + if err = json.Unmarshal(responsePayload, &responseObj); err != nil { return &CertificateVerificationResponse{}, fmt.Errorf("cannot unmarshall response object: %w", err) } diff --git a/pkg/capabilities/crypto/crypto_test.go b/pkg/capabilities/crypto/crypto_test.go index 030edc3..ce9f97c 100644 --- a/pkg/capabilities/crypto/crypto_test.go +++ b/pkg/capabilities/crypto/crypto_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" ) @@ -23,7 +23,7 @@ func TestV1IsCertificateTrusted(t *testing.T) { Encoding: Pem, Data: []rune("certificate2"), }} - not_after := "2021-10-01T00:00:00Z" + notAfter := "2021-10-01T00:00:00Z" verificationResponse := CertificateVerificationResponse{ Trusted: true, @@ -42,11 +42,11 @@ func TestV1IsCertificateTrusted(t *testing.T) { Return(verificationPayload, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } - res, err := VerifyCert(host, cert, chain, not_after) + res, err := VerifyCert(host, cert, chain, notAfter) if err != nil { t.Fatalf("unexpected error: %v", err) } diff --git a/pkg/capabilities/crypto/types.go b/pkg/capabilities/crypto/types.go index 83d70df..015fb44 100644 --- a/pkg/capabilities/crypto/types.go +++ b/pkg/capabilities/crypto/types.go @@ -1,6 +1,6 @@ package crypto -// A x509 certificate +// A x509 certificate. type Certificate struct { // Which encoding is used by the certificate Encoding CertificateEncoding `json:"encoding"` diff --git a/pkg/capabilities/kubernetes/kubernetes.go b/pkg/capabilities/kubernetes/kubernetes.go index 9ceab70..64b001a 100644 --- a/pkg/capabilities/kubernetes/kubernetes.go +++ b/pkg/capabilities/kubernetes/kubernetes.go @@ -4,13 +4,13 @@ import ( "encoding/json" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) // ListResourcesByNamespace gets all the Kubernetes resources defined inside of // the given namespace -// Note: cannot be used for cluster-wide resources -func ListResourcesByNamespace(h *cap.Host, req ListResourcesByNamespaceRequest) ([]byte, error) { +// Note: cannot be used for cluster-wide resources. +func ListResourcesByNamespace(h *capabilities.Host, req ListResourcesByNamespaceRequest) ([]byte, error) { payload, err := json.Marshal(req) if err != nil { return []byte{}, fmt.Errorf("cannot serialize request object: %w", err) @@ -26,8 +26,8 @@ func ListResourcesByNamespace(h *cap.Host, req ListResourcesByNamespaceRequest) } // ListResources gets all the Kubernetes resources defined inside of the cluster. -// Note: this has be used for cluster-wide resources -func ListResources(h *cap.Host, req ListAllResourcesRequest) ([]byte, error) { +// Note: this has be used for cluster-wide resources. +func ListResources(h *capabilities.Host, req ListAllResourcesRequest) ([]byte, error) { payload, err := json.Marshal(req) if err != nil { return []byte{}, fmt.Errorf("cannot serialize request object: %w", err) @@ -43,7 +43,7 @@ func ListResources(h *cap.Host, req ListAllResourcesRequest) ([]byte, error) { } // GetResource gets a specific Kubernetes resource. -func GetResource(h *cap.Host, req GetResourceRequest) ([]byte, error) { +func GetResource(h *capabilities.Host, req GetResourceRequest) ([]byte, error) { payload, err := json.Marshal(req) if err != nil { return []byte{}, fmt.Errorf("cannot serialize request object: %w", err) diff --git a/pkg/capabilities/kubernetes/kubernetes_test.go b/pkg/capabilities/kubernetes/kubernetes_test.go index 797256b..a15840e 100644 --- a/pkg/capabilities/kubernetes/kubernetes_test.go +++ b/pkg/capabilities/kubernetes/kubernetes_test.go @@ -3,7 +3,7 @@ package kubernetes import ( "testing" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" ) @@ -19,7 +19,7 @@ func TestKubernetesListResourcesByNamespace(t *testing.T) { Return([]byte{}, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } @@ -51,7 +51,7 @@ func TestKubernetesListResources(t *testing.T) { Return([]byte{}, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } @@ -82,7 +82,7 @@ func TestKubernetesGetResource(t *testing.T) { Return([]byte{}, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } namespace := "default" diff --git a/pkg/capabilities/kubernetes/types.go b/pkg/capabilities/kubernetes/types.go index af42680..b8af747 100644 --- a/pkg/capabilities/kubernetes/types.go +++ b/pkg/capabilities/kubernetes/types.go @@ -1,6 +1,6 @@ package kubernetes -// Set of parameters used by the `list_resources_by_namespace` function +// Set of parameters used by the `list_resources_by_namespace` function. type ListResourcesByNamespaceRequest struct { // apiVersion of the resource (v1 for core group, groupName/groupVersions for other). APIVersion string `json:"api_version"` @@ -16,7 +16,7 @@ type ListResourcesByNamespaceRequest struct { FieldSelector *string `json:"field_selector,omitempty"` } -// Set of parameters used by the `list_all_resources` function +// Set of parameters used by the `list_all_resources` function. type ListAllResourcesRequest struct { // apiVersion of the resource (v1 for core group, groupName/groupVersions for other). APIVersion string `json:"api_version"` @@ -30,7 +30,7 @@ type ListAllResourcesRequest struct { FieldSelector *string `json:"field_selector,omitempty"` } -// Set of parameters used by the `get_resource` function +// Set of parameters used by the `get_resource` function. type GetResourceRequest struct { APIVersion string `json:"api_version"` // Singular PascalCase name of the resource diff --git a/pkg/capabilities/net/net.go b/pkg/capabilities/net/net.go index aaeebb2..8fbc5e3 100644 --- a/pkg/capabilities/net/net.go +++ b/pkg/capabilities/net/net.go @@ -4,11 +4,11 @@ import ( "encoding/json" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) -// LookupHost looks up the addresses for a given hostname via DNS -func LookupHost(h *cap.Host, host string) ([]string, error) { +// LookupHost looks up the addresses for a given hostname via DNS. +func LookupHost(h *capabilities.Host, host string) ([]string, error) { // build request, e.g: `"localhost"` payload, err := json.Marshal(host) if err != nil { @@ -22,7 +22,7 @@ func LookupHost(h *cap.Host, host string) ([]string, error) { } response := LookupHostResponse{} - if err := json.Unmarshal(responsePayload, &response); err != nil { + if err = json.Unmarshal(responsePayload, &response); err != nil { return []string{}, fmt.Errorf("cannot unmarshall response: %w", err) } diff --git a/pkg/capabilities/net/net_test.go b/pkg/capabilities/net/net_test.go index e445730..bafd09e 100644 --- a/pkg/capabilities/net/net_test.go +++ b/pkg/capabilities/net/net_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" ) @@ -28,7 +28,7 @@ func TestV1DnsLookupHost(t *testing.T) { Return(lookupPayload, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } diff --git a/pkg/capabilities/net/types.go b/pkg/capabilities/net/types.go index 95df347..eaf8b7e 100644 --- a/pkg/capabilities/net/types.go +++ b/pkg/capabilities/net/types.go @@ -3,7 +3,7 @@ package net // We don't need to expose that to consumers of the library // This is a glorified wrapper needed to unmarshal a list // of string inside of TinyGo. As of release 0.29.0, unmarshal a simple -// list of string causes a runtime panic +// list of string causes a runtime panic. type LookupHostResponse struct { // List of IP addresses associated with the host Ips []string `json:"ips"` diff --git a/pkg/capabilities/oci/manifest/manifest.go b/pkg/capabilities/oci/manifest/manifest.go index 89a6945..a0e4108 100644 --- a/pkg/capabilities/oci/manifest/manifest.go +++ b/pkg/capabilities/oci/manifest/manifest.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) // GetOCIManifest fetches the OCI manifest for the given image URI. @@ -14,8 +14,8 @@ import ( // https://github.com/opencontainers/image-spec/blob/main/manifest.md // https://github.com/opencontainers/image-spec/blob/main/image-index.md // Arguments: -// * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) -func GetOCIManifest(h *cap.Host, image string) (*OciImageManifestResponse, error) { +// * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`). +func GetOCIManifest(h *capabilities.Host, image string) (*OciImageManifestResponse, error) { // build request payload, e.g: `"ghcr.io/kubewarden/policies/pod-privileged:v0.1.10"` payload, err := json.Marshal(image) if err != nil { @@ -29,8 +29,8 @@ func GetOCIManifest(h *cap.Host, image string) (*OciImageManifestResponse, error } response := OciImageManifestResponse{} - if err := json.Unmarshal(responsePayload, &response); err != nil { - return nil, errors.Join(fmt.Errorf("failed to parse response from the host"), err) + if err = json.Unmarshal(responsePayload, &response); err != nil { + return nil, errors.Join(errors.New("failed to parse response from the host"), err) } return &response, nil } diff --git a/pkg/capabilities/oci/manifest/manifest_test.go b/pkg/capabilities/oci/manifest/manifest_test.go index deeb643..65f2cf4 100644 --- a/pkg/capabilities/oci/manifest/manifest_test.go +++ b/pkg/capabilities/oci/manifest/manifest_test.go @@ -8,7 +8,7 @@ import ( "github.com/kubewarden/policy-sdk-go/constants" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" digest "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go/v1" @@ -16,14 +16,14 @@ import ( "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" ) -func buildHostMock(imageURI string, returnPayload []byte) (*cap.Host, error) { +func buildHostMock(imageURI string, returnPayload []byte) (*capabilities.Host, error) { mockWapcClient := &mocks.MockWapcClient{} expectedPayload, err := json.Marshal(imageURI) if err != nil { return nil, err } mockWapcClient.EXPECT().HostCall("kubewarden", "oci", "v1/oci_manifest", expectedPayload).Return(returnPayload, nil).Times(1) - return &cap.Host{ + return &capabilities.Host{ Client: mockWapcClient, }, nil } diff --git a/pkg/capabilities/oci/manifest/types.go b/pkg/capabilities/oci/manifest/types.go index f9c01bd..bd9aaba 100644 --- a/pkg/capabilities/oci/manifest/types.go +++ b/pkg/capabilities/oci/manifest/types.go @@ -2,7 +2,9 @@ package manifest import ( "encoding/json" + "errors" "fmt" + "github.com/kubewarden/policy-sdk-go/constants" specs "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -36,7 +38,7 @@ func (r *OciImageManifestResponse) UnmarshalJSON(b []byte) error { } return fmt.Errorf("not a valid media type: %s", indexManifest.MediaType) } - return fmt.Errorf("cannot decode response") + return errors.New("cannot decode response") } func isImageIndexMediaType(mediaType string) bool { diff --git a/pkg/capabilities/oci/manifest_config/manifest.go b/pkg/capabilities/oci/manifest_config/manifest.go index 2a7dfdf..3a348cd 100644 --- a/pkg/capabilities/oci/manifest_config/manifest.go +++ b/pkg/capabilities/oci/manifest_config/manifest.go @@ -5,13 +5,13 @@ import ( "errors" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) // GetOCIManifestAndConfig fetches the OCI manifest and configuration for the given image URI. // Arguments: -// * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) -func GetOCIManifestAndConfig(h *cap.Host, image string) (*OciImageManifestAndConfigResponse, error) { +// * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`). +func GetOCIManifestAndConfig(h *capabilities.Host, image string) (*OciImageManifestAndConfigResponse, error) { // build request payload, e.g: `"ghcr.io/kubewarden/policies/pod-privileged:v0.1.10"` payload, err := json.Marshal(image) if err != nil { @@ -25,8 +25,8 @@ func GetOCIManifestAndConfig(h *cap.Host, image string) (*OciImageManifestAndCon } response := OciImageManifestAndConfigResponse{} - if err := json.Unmarshal(responsePayload, &response); err != nil { - return nil, errors.Join(fmt.Errorf("failed to parse response from the host"), err) + if err = json.Unmarshal(responsePayload, &response); err != nil { + return nil, errors.Join(errors.New("failed to parse response from the host"), err) } return &response, nil } diff --git a/pkg/capabilities/oci/manifest_config/manifest_test.go b/pkg/capabilities/oci/manifest_config/manifest_test.go index 7e4e69c..daf9e76 100644 --- a/pkg/capabilities/oci/manifest_config/manifest_test.go +++ b/pkg/capabilities/oci/manifest_config/manifest_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" digest "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go/v1" @@ -14,14 +14,14 @@ import ( "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" ) -func buildHostMock(imageURI string, returnPayload []byte) (*cap.Host, error) { +func buildHostMock(imageURI string, returnPayload []byte) (*capabilities.Host, error) { mockWapcClient := &mocks.MockWapcClient{} expectedPayload, err := json.Marshal(imageURI) if err != nil { return nil, err } mockWapcClient.EXPECT().HostCall("kubewarden", "oci", "v1/oci_manifest_config", expectedPayload).Return(returnPayload, nil).Times(1) - return &cap.Host{ + return &capabilities.Host{ Client: mockWapcClient, }, nil } @@ -94,7 +94,7 @@ func TestOciManifestAndConfig(t *testing.T) { t.Fatalf("cannot serialize response object: %v", err) } response := OciImageManifestAndConfigResponse{} - if err := json.Unmarshal(manifestPayload, &response); err != nil { + if err = json.Unmarshal(manifestPayload, &response); err != nil { t.Fatalf("failed to parse response from the host") } diff --git a/pkg/capabilities/oci/manifest_digest/manifest_digest.go b/pkg/capabilities/oci/manifest_digest/manifest_digest.go index cb7585d..2c12d9d 100644 --- a/pkg/capabilities/oci/manifest_digest/manifest_digest.go +++ b/pkg/capabilities/oci/manifest_digest/manifest_digest.go @@ -4,13 +4,13 @@ import ( "encoding/json" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) // GetOCIManifestDigest computes the digest of the OCI object referenced by image // Arguments: -// * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) -func GetOCIManifestDigest(h *cap.Host, image string) (string, error) { +// * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`). +func GetOCIManifestDigest(h *capabilities.Host, image string) (string, error) { // build request payload, e.g: `"ghcr.io/kubewarden/policies/pod-privileged:v0.1.10"` payload, err := json.Marshal(image) if err != nil { @@ -24,7 +24,7 @@ func GetOCIManifestDigest(h *cap.Host, image string) (string, error) { } response := OciManifestResponse{} - if err := json.Unmarshal(responsePayload, &response); err != nil { + if err = json.Unmarshal(responsePayload, &response); err != nil { return "", fmt.Errorf("cannot unmarshall response: %w", err) } diff --git a/pkg/capabilities/oci/manifest_digest/manifest_digest_test.go b/pkg/capabilities/oci/manifest_digest/manifest_digest_test.go index cf1af00..2b9c394 100644 --- a/pkg/capabilities/oci/manifest_digest/manifest_digest_test.go +++ b/pkg/capabilities/oci/manifest_digest/manifest_digest_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" ) @@ -28,7 +28,7 @@ func TestV1ManifestDigest(t *testing.T) { Return(digestPayload, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } diff --git a/pkg/capabilities/oci/manifest_digest/types.go b/pkg/capabilities/oci/manifest_digest/types.go index dcb717c..4c21ee7 100644 --- a/pkg/capabilities/oci/manifest_digest/types.go +++ b/pkg/capabilities/oci/manifest_digest/types.go @@ -3,7 +3,7 @@ package manifest_digest // We don't need to expose that to consumers of the library // This is a glorified wrapper needed to unmarshal a string // inside of TinyGo. As of release 0.29.0, unmarshal a simple -// string causes a runtime panic +// string causes a runtime panic. type OciManifestResponse struct { // digest of the image Digest string `json:"digest"` diff --git a/pkg/capabilities/oci/oci.go b/pkg/capabilities/oci/oci.go index a6ceda6..3274c56 100644 --- a/pkg/capabilities/oci/oci.go +++ b/pkg/capabilities/oci/oci.go @@ -4,7 +4,7 @@ import ( "encoding/json" "fmt" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" ) type HostOCIVerifyVersion int64 @@ -24,7 +24,7 @@ func (s HostOCIVerifyVersion) String() string { return "unknown" } -func Verify(h *cap.Host, requestObj interface{}, operation HostOCIVerifyVersion) (VerificationResponse, error) { +func Verify(h *capabilities.Host, requestObj interface{}, operation HostOCIVerifyVersion) (VerificationResponse, error) { // failsafe return response vr := VerificationResponse{ IsTrusted: false, @@ -43,7 +43,7 @@ func Verify(h *cap.Host, requestObj interface{}, operation HostOCIVerifyVersion) } responseObj := VerificationResponse{} - if err := json.Unmarshal(responsePayload, &responseObj); err != nil { + if err = json.Unmarshal(responsePayload, &responseObj); err != nil { return vr, fmt.Errorf("cannot unmarshall response object: %w", err) } diff --git a/pkg/capabilities/oci/verify_v1/types.go b/pkg/capabilities/oci/verify_v1/types.go index c79fe89..bcbcb61 100644 --- a/pkg/capabilities/oci/verify_v1/types.go +++ b/pkg/capabilities/oci/verify_v1/types.go @@ -3,7 +3,7 @@ package verify_v1 import oci "github.com/kubewarden/policy-sdk-go/pkg/capabilities/oci" // sigstorePubKeysVerify represents the WaPC JSON contract, used for marshalling -// and unmarshalling payloads to wapc host calls +// and unmarshalling payloads to wapc host calls. type sigstorePubKeysVerify struct { // String pointing to the object (e.g.: `registry.testing.lan/busybox:1.0.0`) Image string `json:"image"` @@ -19,7 +19,7 @@ type sigstorePubKeysVerifyRequest struct { } // sigstoreKeylessVerify represents the WaPC JSON contract, used for marshalling -// and unmarshalling payloads to wapc host calls +// and unmarshalling payloads to wapc host calls. type sigstoreKeylessVerify struct { // String pointing to the object (e.g.: `registry.testing.lan/busybox:1.0.0`) Image string `json:"image"` diff --git a/pkg/capabilities/oci/verify_v1/verify_v1.go b/pkg/capabilities/oci/verify_v1/verify_v1.go index 4f7c824..0d63f6e 100644 --- a/pkg/capabilities/oci/verify_v1/verify_v1.go +++ b/pkg/capabilities/oci/verify_v1/verify_v1.go @@ -1,7 +1,7 @@ package verify_v1 import ( - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" oci "github.com/kubewarden/policy-sdk-go/pkg/capabilities/oci" ) @@ -9,8 +9,8 @@ import ( // Arguments // * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) // * pubKeys: list of PEM encoded keys that must have been used to sign the OCI object -// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyPubKeys(h *cap.Host, image string, pubKeys []string, annotations map[string]string) (oci.VerificationResponse, error) { +// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact. +func VerifyPubKeys(h *capabilities.Host, image string, pubKeys []string, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := sigstorePubKeysVerifyRequest{ SigstorePubKeysVerify: sigstorePubKeysVerify{ Image: image, @@ -26,8 +26,8 @@ func VerifyPubKeys(h *cap.Host, image string, pubKeys []string, annotations map[ // Arguments // * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) // * keyless: list of KeylessInfo pairs, containing Issuer and Subject info from OIDC providers -// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyKeyless(h *cap.Host, image string, keyless []oci.KeylessInfo, annotations map[string]string) (oci.VerificationResponse, error) { +// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact. +func VerifyKeyless(h *capabilities.Host, image string, keyless []oci.KeylessInfo, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := sigstoreKeylessVerifyRequest{ SigstoreKeylessVerify: sigstoreKeylessVerify{ Image: image, diff --git a/pkg/capabilities/oci/verify_v1/verify_v1_test.go b/pkg/capabilities/oci/verify_v1/verify_v1_test.go index 63ed413..ac73b66 100644 --- a/pkg/capabilities/oci/verify_v1/verify_v1_test.go +++ b/pkg/capabilities/oci/verify_v1/verify_v1_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" oci "github.com/kubewarden/policy-sdk-go/pkg/capabilities/oci" "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" @@ -12,7 +12,7 @@ import ( type v1VerifyTestCase struct { request interface{} - checkIsTrustedFunc func(host *cap.Host, request interface{}) (bool, error) + checkIsTrustedFunc func(host *capabilities.Host, request interface{}) (bool, error) } func TestV1Verify(t *testing.T) { @@ -63,7 +63,7 @@ func TestV1Verify(t *testing.T) { Return(verificationPayload, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } @@ -78,7 +78,7 @@ func TestV1Verify(t *testing.T) { } } -func CheckPubKeysTrustedV1(host *cap.Host, request interface{}) (bool, error) { +func CheckPubKeysTrustedV1(host *capabilities.Host, request interface{}) (bool, error) { requestPubKeys := request.(sigstorePubKeysVerifyRequest) res, err := VerifyPubKeys(host, requestPubKeys.SigstorePubKeysVerify.Image, requestPubKeys.SigstorePubKeysVerify.PubKeys, requestPubKeys.SigstorePubKeysVerify.Annotations) if err != nil { @@ -87,7 +87,7 @@ func CheckPubKeysTrustedV1(host *cap.Host, request interface{}) (bool, error) { return res.IsTrusted, nil } -func CheckKeylessTrustedV1(host *cap.Host, request interface{}) (bool, error) { +func CheckKeylessTrustedV1(host *capabilities.Host, request interface{}) (bool, error) { requestKeyless := request.(sigstoreKeylessVerifyRequest) res, err := VerifyKeyless(host, requestKeyless.SigstoreKeylessVerify.Image, requestKeyless.SigstoreKeylessVerify.Keyless, requestKeyless.SigstoreKeylessVerify.Annotations) if err != nil { diff --git a/pkg/capabilities/oci/verify_v2/types.go b/pkg/capabilities/oci/verify_v2/types.go index b43d944..1adf945 100644 --- a/pkg/capabilities/oci/verify_v2/types.go +++ b/pkg/capabilities/oci/verify_v2/types.go @@ -10,11 +10,11 @@ type KeylessPrefixInfo struct { // Valid prefix of the Subject field in the signature used to authenticate // against the OIDC provider. It forms a valid URL on its own, and will get // sanitized by appending `/` to protect against typosquatting - UrlPrefix string `json:"url_prefix"` + UrlPrefix string `json:"url_prefix"` //nolint:revive // We cannot change the name of this field without breaking the compatibility } // SigstorePubKeysVerify represents the WaPC JSON contract, used for marshalling -// and unmarshalling payloads to wapc host calls +// and unmarshalling payloads to wapc host calls. type SigstorePubKeysVerify struct { Type SigstorePubKeyVerifyType `json:"type"` // String pointing to the object (e.g.: `registry.testing.lan/busybox:1.0.0`) @@ -27,7 +27,7 @@ type SigstorePubKeysVerify struct { } // SigstoreKeylessVerifyExact represents the WaPC JSON contract, used for marshalling -// and unmarshalling payloads to wapc host calls +// and unmarshalling payloads to wapc host calls. type SigstoreKeylessVerifyExact struct { Type SigstoreKeylessVerifyType `json:"type"` // String pointing to the object (e.g.: `registry.testing.lan/busybox:1.0.0`) @@ -40,7 +40,7 @@ type SigstoreKeylessVerifyExact struct { } // sigstoreKeylessVerify represents the WaPC JSON contract, used for marshalling -// and unmarshalling payloads to wapc host calls +// and unmarshalling payloads to wapc host calls. type SigstoreKeylessPrefixVerify struct { Type SigstoreKeylessPrefixVerifyType `json:"type"` // String pointing to the object (e.g.: `registry.testing.lan/busybox:1.0.0`) diff --git a/pkg/capabilities/oci/verify_v2/verify_v2.go b/pkg/capabilities/oci/verify_v2/verify_v2.go index 0f590e5..a261c63 100644 --- a/pkg/capabilities/oci/verify_v2/verify_v2.go +++ b/pkg/capabilities/oci/verify_v2/verify_v2.go @@ -3,7 +3,7 @@ package verify_v2 import ( "encoding/json" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" oci "github.com/kubewarden/policy-sdk-go/pkg/capabilities/oci" ) @@ -41,8 +41,8 @@ func (e SigstoreCertificateVerifyType) MarshalJSON() ([]byte, error) { // Arguments // * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) // * pubKeys: list of PEM encoded keys that must have been used to sign the OCI object -// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyPubKeysImage(h *cap.Host, image string, pubKeys []string, annotations map[string]string) (oci.VerificationResponse, error) { +// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact. +func VerifyPubKeysImage(h *capabilities.Host, image string, pubKeys []string, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := SigstorePubKeysVerify{ Image: image, PubKeys: pubKeys, @@ -56,8 +56,8 @@ func VerifyPubKeysImage(h *cap.Host, image string, pubKeys []string, annotations // Arguments // * image: image to be verified (e.g.: `registry.testing.lan/busybox:1.0.0`) // * keyless: list of KeylessInfo pairs, containing Issuer and Subject info from OIDC providers -// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyKeylessExactMatch(h *cap.Host, image string, keyless []oci.KeylessInfo, annotations map[string]string) (oci.VerificationResponse, error) { +// * annotations: annotations that must have been provided by all signers when they signed the OCI artifact. +func VerifyKeylessExactMatch(h *capabilities.Host, image string, keyless []oci.KeylessInfo, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := SigstoreKeylessVerifyExact{ Image: image, Keyless: keyless, @@ -74,8 +74,8 @@ func VerifyKeylessExactMatch(h *cap.Host, image string, keyless []oci.KeylessInf // # Arguments // * `image` - image to be verified // * `keyless` - list of issuers and subjects -// * `annotations` - annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyKeylessPrefixMatch(h *cap.Host, image string, keylessPrefix []KeylessPrefixInfo, annotations map[string]string) (oci.VerificationResponse, error) { +// * `annotations` - annotations that must have been provided by all signers when they signed the OCI artifact. +func VerifyKeylessPrefixMatch(h *capabilities.Host, image string, keylessPrefix []KeylessPrefixInfo, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := SigstoreKeylessPrefixVerify{ Image: image, KeylessPrefix: keylessPrefix, @@ -91,8 +91,8 @@ func VerifyKeylessPrefixMatch(h *cap.Host, image string, keylessPrefix []Keyless // * `image` - image to be verified // * `owner` - owner of the repository. E.g: octocat // * `repo` - Optional. repo of the GH Action workflow that signed the artifact. E.g: example-repo. Optional. -// * `annotations` - annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyKeylessGithubActions(h *cap.Host, image string, owner string, repo string, annotations map[string]string) (oci.VerificationResponse, error) { +// * `annotations` - annotations that must have been provided by all signers when they signed the OCI artifact. +func VerifyKeylessGithubActions(h *capabilities.Host, image string, owner string, repo string, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := SigstoreGithubActionsVerify{ Image: image, Owner: owner, @@ -116,7 +116,7 @@ func VerifyKeylessGithubActions(h *cap.Host, image string, owner string, repo st // It is recommended to set this value to `true` to have a more secure // verification process. // - `annotations` - annotations that must have been provided by all signers when they signed the OCI artifact -func VerifyCertificate(h *cap.Host, image string, certificate []rune, certificateChain [][]rune, requireRekorBundle bool, annotations map[string]string) (oci.VerificationResponse, error) { +func VerifyCertificate(h *capabilities.Host, image string, certificate []rune, certificateChain [][]rune, requireRekorBundle bool, annotations map[string]string) (oci.VerificationResponse, error) { requestObj := SigstoreCertificateVerify{ Image: image, Certificate: certificate, diff --git a/pkg/capabilities/oci/verify_v2/verify_v2_test.go b/pkg/capabilities/oci/verify_v2/verify_v2_test.go index 3ff6163..025b0a7 100644 --- a/pkg/capabilities/oci/verify_v2/verify_v2_test.go +++ b/pkg/capabilities/oci/verify_v2/verify_v2_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "testing" - cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" + "github.com/kubewarden/policy-sdk-go/pkg/capabilities" "github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" oci "github.com/kubewarden/policy-sdk-go/pkg/capabilities/oci" ) @@ -12,7 +12,7 @@ import ( type v2VerifyTestCase struct { request interface{} expectedPayload string - checkIsTrustedFunc func(host *cap.Host, request interface{}) (bool, error) + checkIsTrustedFunc func(host *capabilities.Host, request interface{}) (bool, error) } func TestV2Verify(t *testing.T) { @@ -97,7 +97,7 @@ func TestV2Verify(t *testing.T) { Return(verificationPayload, nil). Times(1) - host := &cap.Host{ + host := &capabilities.Host{ Client: mockWapcClient, } @@ -112,7 +112,7 @@ func TestV2Verify(t *testing.T) { } } -func CheckPubKeysImageTrusted(host *cap.Host, request interface{}) (bool, error) { +func CheckPubKeysImageTrusted(host *capabilities.Host, request interface{}) (bool, error) { requestPubKeys := request.(SigstorePubKeysVerify) res, err := VerifyPubKeysImage(host, requestPubKeys.Image, requestPubKeys.PubKeys, requestPubKeys.Annotations) if err != nil { @@ -121,7 +121,7 @@ func CheckPubKeysImageTrusted(host *cap.Host, request interface{}) (bool, error) return res.IsTrusted, nil } -func CheckKeylessExactMatchTrusted(host *cap.Host, request interface{}) (bool, error) { +func CheckKeylessExactMatchTrusted(host *capabilities.Host, request interface{}) (bool, error) { requestKeylessExactMatch := request.(SigstoreKeylessVerifyExact) res, err := VerifyKeylessExactMatch(host, requestKeylessExactMatch.Image, requestKeylessExactMatch.Keyless, requestKeylessExactMatch.Annotations) if err != nil { @@ -130,7 +130,7 @@ func CheckKeylessExactMatchTrusted(host *cap.Host, request interface{}) (bool, e return res.IsTrusted, nil } -func CheckKeylessPrefixMatchTrusted(host *cap.Host, request interface{}) (bool, error) { +func CheckKeylessPrefixMatchTrusted(host *capabilities.Host, request interface{}) (bool, error) { requestKeylessPrefixMatch := request.(SigstoreKeylessPrefixVerify) res, err := VerifyKeylessPrefixMatch(host, requestKeylessPrefixMatch.Image, requestKeylessPrefixMatch.KeylessPrefix, requestKeylessPrefixMatch.Annotations) if err != nil { @@ -139,7 +139,7 @@ func CheckKeylessPrefixMatchTrusted(host *cap.Host, request interface{}) (bool, return res.IsTrusted, nil } -func CheckKeylessGithubActionsTrusted(host *cap.Host, request interface{}) (bool, error) { +func CheckKeylessGithubActionsTrusted(host *capabilities.Host, request interface{}) (bool, error) { requestKeylessGithubActions := request.(SigstoreGithubActionsVerify) res, err := VerifyKeylessGithubActions(host, requestKeylessGithubActions.Image, requestKeylessGithubActions.Owner, requestKeylessGithubActions.Repo, requestKeylessGithubActions.Annotations) if err != nil { @@ -148,7 +148,7 @@ func CheckKeylessGithubActionsTrusted(host *cap.Host, request interface{}) (bool return res.IsTrusted, nil } -func CheckCertificateTrusted(host *cap.Host, request interface{}) (bool, error) { +func CheckCertificateTrusted(host *capabilities.Host, request interface{}) (bool, error) { requestCertificate := request.(SigstoreCertificateVerify) res, err := VerifyCertificate(host, requestCertificate.Image, requestCertificate.Certificate, requestCertificate.CertificateChain, requestCertificate.RequireRekorBundle, requestCertificate.Annotations) diff --git a/protocol/types.go b/protocol/types.go index 0315222..7b46b0f 100644 --- a/protocol/types.go +++ b/protocol/types.go @@ -4,7 +4,7 @@ import ( "encoding/json" ) -// Structure defining the response given when validating a request +// Structure defining the response given when validating a request. type ValidationResponse struct { Accepted bool `json:"accepted"` // Optional - ignored if accepted @@ -15,14 +15,14 @@ type ValidationResponse struct { MutatedObject interface{} `json:"mutated_object,omitempty"` } -// The response sent by a policy when validating its settings +// The response sent by a policy when validating its settings. type SettingsValidationResponse struct { Valid bool `json:"valid"` // Optional - ignored if valid Message *string `json:"message,omitempty"` } -// The object received by the validate() function of Kubewarden policies +// The object received by the validate() function of Kubewarden policies. type ValidationRequest struct { // The request to be evaluated Request KubernetesAdmissionRequest `json:"request"` @@ -35,62 +35,89 @@ type ValidationRequest struct { Settings json.RawMessage `json:"settings"` } -// Kubernetes' [AdmissionReview](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) +// Kubernetes' +// [AdmissionReview](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) // request. type KubernetesAdmissionRequest struct { - // UID is an identifier for the individual request/response. It allows us to distinguish instances of requests which are - // otherwise identical (parallel requests, requests when earlier requests did not modify etc) - // The UID is meant to track the round trip (request/response) between the KAS and the WebHook, not the user request. - // It is suitable for correlating log entries between the webhook and apiserver, for either auditing or debugging. - Uid string `json:"uid"` - - // Kind is the fully-qualified type of object being submitted (for example, v1.Pod or autoscaling.v1.Scale) + // UID is an identifier for the individual request/response. It allows + // us to distinguish instances of requests which are otherwise + // identical (parallel requests, requests when earlier requests did not + // modify etc) The UID is meant to track the round trip + // (request/response) between the KAS and the WebHook, not the user + // request. It is suitable for correlating log entries between the + // webhook and apiserver, for either auditing or debugging. + Uid string `json:"uid"` //nolint:revive // We cannot change this field name without breaking compatibility + + // Kind is the fully-qualified type of object being submitted (for + // example, v1.Pod or autoscaling.v1.Scale) Kind GroupVersionKind `json:"kind"` - // Resource is the fully-qualified resource being requested (for example, v1.pods) + // Resource is the fully-qualified resource being requested (for + // example, v1.pods) Resource GroupVersionResource `json:"resource"` - // SubResource is the subresource being requested, if any (for example, "status" or "scale") + // SubResource is the subresource being requested, if any (for example, + // "status" or "scale") SubResource string `json:"subResource"` - // RequestKind is the fully-qualified type of the original API request (for example, v1.Pod or autoscaling.v1.Scale). - // If this is specified and differs from the value in "kind", an equivalent match and conversion was performed. + // RequestKind is the fully-qualified type of the original API request + // (for example, v1.Pod or autoscaling.v1.Scale). If this is specified + // and differs from the value in "kind", an equivalent match and + // conversion was performed. // - // For example, if deployments can be modified via apps/v1 and apps/v1beta1, and a webhook registered a rule of - // `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` and `matchPolicy: Equivalent`, - // an API request to apps/v1beta1 deployments would be converted and sent to the webhook - // with `kind: {group:"apps", version:"v1", kind:"Deployment"}` (matching the rule the webhook registered for), - // and `requestKind: {group:"apps", version:"v1beta1", kind:"Deployment"}` (indicating the kind of the original API request). + // For example, if deployments can be modified via apps/v1 and + // apps/v1beta1, and a webhook registered a rule of + // `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` + // and `matchPolicy: Equivalent`, an API request to apps/v1beta1 + // deployments would be converted and sent to the webhook with `kind: + // {group:"apps", version:"v1", kind:"Deployment"}` (matching the rule + // the webhook registered for), and `requestKind: {group:"apps", + // version:"v1beta1", kind:"Deployment"}` (indicating the kind of the + // original API request). // - // See documentation for the "matchPolicy" field in the webhook configuration type for more details. + // See documentation for the "matchPolicy" field in the webhook + // configuration type for more details. RequestKind GroupVersionKind `json:"requestKind"` - // RequestResource is the fully-qualified resource of the original API request (for example, v1.pods). - // If this is specified and differs from the value in "resource", an equivalent match and conversion was performed. + // RequestResource is the fully-qualified resource of the original API + // request (for example, v1.pods). If this is specified and differs + // from the value in "resource", an equivalent match and conversion was + // performed. // - // For example, if deployments can be modified via apps/v1 and apps/v1beta1, and a webhook registered a rule of - // `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` and `matchPolicy: Equivalent`, - // an API request to apps/v1beta1 deployments would be converted and sent to the webhook - // with `resource: {group:"apps", version:"v1", resource:"deployments"}` (matching the resource the webhook registered for), - // and `requestResource: {group:"apps", version:"v1beta1", resource:"deployments"}` (indicating the resource of the original API request). + // For example, if deployments can be modified via apps/v1 and + // apps/v1beta1, and a webhook registered a rule of + // `apiGroups:["apps"], apiVersions:["v1"], resources: ["deployments"]` + // and `matchPolicy: Equivalent`, an API request to apps/v1beta1 + // deployments would be converted and sent to the webhook with + // `resource: {group:"apps", version:"v1", resource:"deployments"}` + // (matching the resource the webhook registered for), and + // `requestResource: {group:"apps", version:"v1beta1", + // resource:"deployments"}` (indicating the resource of the original + // API request). // - // See documentation for the "matchPolicy" field in the webhook configuration type. + // See documentation for the "matchPolicy" field in the webhook + // configuration type. RequestResource GroupVersionKind `json:"requestResource"` - // RequestSubResource is the name of the subresource of the original API request, if any (for example, "status" or "scale") - // If this is specified and differs from the value in "subResource", an equivalent match and conversion was performed. - // See documentation for the "matchPolicy" field in the webhook configuration type. + // RequestSubResource is the name of the subresource of the original + // API request, if any (for example, "status" or "scale") If this is + // specified and differs from the value in "subResource", an equivalent + // match and conversion was performed. See documentation for the + // "matchPolicy" field in the webhook configuration type. RequestSubResource string `json:"requestSubResource"` - // Name is the name of the object as presented in the request. On a CREATE operation, the client may omit name and - // rely on the server to generate the name. If that is the case, this field will contain an empty string. + // Name is the name of the object as presented in the request. On a + // CREATE operation, the client may omit name and rely on the server to + // generate the name. If that is the case, this field will contain an + // empty string. Name string `json:"name"` // Namespace is the namespace associated with the request (if any). Namespace string `json:"namespace"` - // Operation is the operation being performed. This may be different than the operation - // requested. e.g. a patch can result in either a CREATE or UPDATE Operation. + // Operation is the operation being performed. This may be different + // than the operation requested. e.g. a patch can result in either a + // CREATE or UPDATE Operation. Operation string `json:"operation"` // UserInfo is information about the requesting user @@ -104,52 +131,55 @@ type KubernetesAdmissionRequest struct { // type that implements the json interfaces. Object json.RawMessage `json:"object"` - // OldObject is the existing object. Only populated for DELETE and UPDATE requests. + // OldObject is the existing object. Only populated for DELETE and + // UPDATE requests. // - // Note, the attributes holds the unmarshalled []bytes as found inside of - // original JSON object. - // This can then be parsed using `json.Unmarshal()` into a proper - // type that implements the json interfaces. + // Note, the attributes holds the unmarshalled []bytes as found inside + // of original JSON object. This can then be parsed using + // `json.Unmarshal()` into a proper type that implements the json + // interfaces. OldObject json.RawMessage `json:"oldObject"` - // DryRun indicates that modifications will definitely not be persisted for this request. - // Defaults to false. + // DryRun indicates that modifications will definitely not be persisted + // for this request. Defaults to false. DryRun bool `json:"dryRun"` - // Options is the operation option structure of the operation being performed. - // e.g. `meta.k8s.io/v1.DeleteOptions` or `meta.k8s.io/v1.CreateOptions`. This may be - // different than the options the caller provided. e.g. for a patch request the performed + // Options is the operation option structure of the operation being + // performed. e.g. `meta.k8s.io/v1.DeleteOptions` or + // `meta.k8s.io/v1.CreateOptions`. This may be different than the + // options the caller provided. e.g. for a patch request the performed // Operation might be a CREATE, in which case the Options will a - // `meta.k8s.io/v1.CreateOptions` even though the caller provided `meta.k8s.io/v1.PatchOptions`. + // `meta.k8s.io/v1.CreateOptions` even though the caller provided + // `meta.k8s.io/v1.PatchOptions`. // - // Note, the attributes holds the unmarshalled []bytes as found inside of - // original JSON object. - // This can then be parsed using `json.Unmarshal()` into a proper - // type that implements the json interfaces. + // Note, the attributes holds the unmarshalled []bytes as found inside + // of original JSON object. This can then be parsed using + // `json.Unmarshal()` into a proper type that implements the json + // interfaces. Options json.RawMessage `json:"options"` } -// GroupVersionKind unambiguously identifies a kind +// GroupVersionKind unambiguously identifies a kind. type GroupVersionKind struct { Group string `json:"group"` Version string `json:"version"` Kind string `json:"kind"` } -// GroupVersionResource unambiguously identifies a resource +// GroupVersionResource unambiguously identifies a resource. type GroupVersionResource struct { Group string `json:"group"` Version string `json:"version"` Kind string `json:"kind"` } -// UserInfo holds information about the user who made the request +// UserInfo holds information about the user who made the request. type UserInfo struct { Username string `json:"username"` Groups []string `json:"groups"` - // Note, the attributes holds the unmarshalled []bytes as found inside of - // original JSON object. - // This can then be parsed using `json.Unmarshal()` into a proper - // type that implements the json interfaces. + // Note, the attributes holds the unmarshalled []bytes as found inside + // of original JSON object. This can then be parsed using + // `json.Unmarshal()` into a proper type that implements the json + // interfaces. Extra json.RawMessage `json:"extra,omitempty"` } diff --git a/testing/helpers.go b/testing/helpers.go index c1133b4..cb0bd9f 100644 --- a/testing/helpers.go +++ b/testing/helpers.go @@ -10,16 +10,16 @@ import ( // BuildValidationRequestFromFixture creates the payload for the invocation of the `validate` // function. -// * `req_fixture`: path to the json file with a recorded requst to evaluate -// * `settings`: instance of policy settings. Must be serializable to JSON using json -func BuildValidationRequestFromFixture(req_fixture string, settings interface{}) ([]byte, error) { - kubeAdmissionReqRaw, err := os.ReadFile(req_fixture) +// * `reqFixture`: path to the json file with a recorded requst to evaluate +// * `settings`: instance of policy settings. Must be serializable to JSON using json. +func BuildValidationRequestFromFixture(reqFixture string, settings interface{}) ([]byte, error) { + kubeAdmissionReqRaw, err := os.ReadFile(reqFixture) if err != nil { return nil, err } kubeAdmissionReq := kubewarden_protocol.KubernetesAdmissionRequest{} - if err := json.Unmarshal(kubeAdmissionReqRaw, &kubeAdmissionReq); err != nil { + if err = json.Unmarshal(kubeAdmissionReqRaw, &kubeAdmissionReq); err != nil { return nil, err } @@ -39,7 +39,7 @@ func BuildValidationRequestFromFixture(req_fixture string, settings interface{}) // BuildValidationRequest creates the payload for the invocation of the `validate` // function. // * `object`: instance of the object. Must be serializable to JSON using json -// * `settings`: instance of policy settings. Must be serializable to JSON using json +// * `settings`: instance of policy settings. Must be serializable to JSON using json. func BuildValidationRequest(object, settings interface{}) ([]byte, error) { objectRaw, err := json.Marshal(object) if err != nil {