-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: expose capability to get OCI image configuration.
Adds a new function to allow policy author to get the OCI image manifest and configuration from a given OCI image name. Signed-off-by: José Guilherme Vanz <[email protected]>
- Loading branch information
Showing
3 changed files
with
158 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package manifest_config | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
|
||
cap "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) { | ||
// build request payload, e.g: `"ghcr.io/kubewarden/policies/pod-privileged:v0.1.10"` | ||
payload, err := json.Marshal(image) | ||
if err != nil { | ||
return nil, fmt.Errorf("cannot serialize image URI to JSON: %w", err) | ||
} | ||
|
||
// perform host callback | ||
responsePayload, err := h.Client.HostCall("kubewarden", "oci", "v1/oci_manifest_config", payload) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
response := OciImageManifestAndConfigResponse{} | ||
if err := json.Unmarshal(responsePayload, &response); err != nil { | ||
return nil, errors.Join(fmt.Errorf("failed to parse response from the host"), err) | ||
} | ||
return &response, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package manifest_config | ||
|
||
import ( | ||
_ "crypto/sha256" | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
|
||
cap "github.com/kubewarden/policy-sdk-go/pkg/capabilities" | ||
digest "github.com/opencontainers/go-digest" | ||
specs "github.com/opencontainers/image-spec/specs-go/v1" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/kubewarden/policy-sdk-go/pkg/capabilities/mocks" | ||
) | ||
|
||
func buildHostMock(imageURI string, returnPayload []byte) (*cap.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{ | ||
Client: mockWapcClient, | ||
}, nil | ||
} | ||
|
||
func buildManifestAndConfigResponse() interface{} { | ||
manifest := specs.Manifest{ | ||
MediaType: specs.MediaTypeImageManifest, | ||
Config: specs.Descriptor{ | ||
MediaType: specs.MediaTypeDescriptor, | ||
Digest: digest.FromString("mydummydigest"), | ||
Size: 1024, | ||
URLs: []string{"ghcr.io/kubewarden/policy-server:latest"}, | ||
Annotations: map[string]string{"annotation": "value"}, | ||
Platform: &specs.Platform{ | ||
Architecture: "amd64", | ||
OS: "linux", | ||
}, | ||
}, | ||
Layers: []specs.Descriptor{}, | ||
Annotations: map[string]string{"annotation": "value"}, | ||
} | ||
now := time.Now() | ||
image := specs.Image{ | ||
Created: &now, | ||
Author: "kubewarden", | ||
Platform: specs.Platform{ | ||
Architecture: "amd64", | ||
OS: "linux", | ||
OSVersion: "1.0.0", | ||
OSFeatures: []string{"feature1", "feature2"}, | ||
Variant: "variant", | ||
}, | ||
Config: specs.ImageConfig{ | ||
User: "1000", | ||
Cmd: []string{"echo", "hello"}, | ||
Entrypoint: []string{"echo"}, | ||
Env: []string{"key=value"}, | ||
WorkingDir: "/", | ||
Labels: map[string]string{"label": "value"}, | ||
StopSignal: "SIGTERM", | ||
ExposedPorts: map[string]struct{}{"80/tcp": {}}, | ||
Volumes: map[string]struct{}{"/tmp": {}}, | ||
ArgsEscaped: true, | ||
}, | ||
RootFS: specs.RootFS{ | ||
Type: "layers", | ||
DiffIDs: []digest.Digest{digest.FromString("mydummydigest")}, | ||
}, | ||
History: []specs.History{ | ||
{ | ||
Created: &now, | ||
CreatedBy: "kubewarden", | ||
Author: "kubewarden", | ||
Comment: "initial commit", | ||
EmptyLayer: false, | ||
}, | ||
}, | ||
} | ||
return OciImageManifestAndConfigResponse{ | ||
Manifest: &manifest, | ||
Digest: "mydummydigest", | ||
ImageConfig: &image, | ||
} | ||
} | ||
|
||
func TestOciManifestAndConfig(t *testing.T) { | ||
manifest := buildManifestAndConfigResponse() | ||
manifestPayload, err := json.Marshal(manifest) | ||
if err != nil { | ||
t.Fatalf("cannot serialize response object: %v", err) | ||
} | ||
response := OciImageManifestAndConfigResponse{} | ||
if err := json.Unmarshal(manifestPayload, &response); err != nil { | ||
t.Fatalf("failed to parse response from the host") | ||
} | ||
|
||
imageURI := "myimage:latest" | ||
host, err := buildHostMock(imageURI, manifestPayload) | ||
if err != nil { | ||
t.Fatalf("cannot build host mock: %q", err) | ||
} | ||
|
||
res, err := GetOCIManifestAndConfig(host, imageURI) | ||
if err != nil { | ||
t.Fatalf("unexpected error: %v", err) | ||
} | ||
|
||
if diff := cmp.Diff(*res, manifest); diff != "" { | ||
t.Fatalf("invalid manifest and config response:\n%s", diff) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package manifest_config | ||
|
||
import ( | ||
specs "github.com/opencontainers/image-spec/specs-go/v1" | ||
) | ||
|
||
type OciImageManifestAndConfigResponse struct { | ||
Manifest *specs.Manifest `json:"manifest"` | ||
Digest string `json:"digest"` | ||
ImageConfig *specs.Image `json:"config"` | ||
} |