Skip to content

Commit

Permalink
feat: plugins as OCI artifacts (#519)
Browse files Browse the repository at this point in the history
Signed-off-by: Akash Singhal <[email protected]>
  • Loading branch information
noelbundick-msft authored Feb 1, 2023
1 parent 266cdfb commit 1e69abe
Show file tree
Hide file tree
Showing 25 changed files with 618 additions and 4 deletions.
4 changes: 4 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ RUN curl -Lo oras.tar.gz https://github.com/oras-project/oras/releases/download/
&& mv oras-install/oras /usr/local/bin/ \
&& rm -rf ./oras-install oras.tar.gz

ARG KUBEBUILDER_VERSION="3.8.0"
RUN curl -L https://github.com/kubernetes-sigs/kubebuilder/releases/download/v${KUBEBUILDER_VERSION}/kubebuilder_linux_amd64 -o /usr/local/bin/kubebuilder \
&& chmod +x /usr/local/bin/kubebuilder

# [Optional] Uncomment this section to install additional OS packages.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends protobuf-compiler libprotobuf-dev
Expand Down
9 changes: 8 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/ratify",
"env": {
"RATIFY_DYNAMIC_PLUGINS": "1"
},
"args": [
"verify",
"-s",
Expand All @@ -22,6 +25,9 @@
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd/ratify",
"env": {
"RATIFY_DYNAMIC_PLUGINS": "1"
},
"args": [
"serve",
"--http",
Expand All @@ -36,7 +42,8 @@
"mode": "auto",
"program": "${workspaceFolder}/cmd/ratify",
"env": {
"RATIFY_LOG_LEVEL": "debug"
"RATIFY_LOG_LEVEL": "debug",
"RATIFY_DYNAMIC_PLUGINS": "1"
},
"args": [
"serve",
Expand Down
31 changes: 31 additions & 0 deletions api/v1alpha1/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2022.
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 v1alpha1

import runtime "k8s.io/apimachinery/pkg/runtime"

// PluginSource defines the fields needed to download a plugin from an OCI Artifact source
type PluginSource struct {
// Important: Run "make" to regenerate code after modifying this file

// OCI Artifact source to download the plugin from
Artifact string `json:"artifact,omitempty"`

// +kubebuilder:pruning:PreserveUnknownFields
// AuthProvider to use to authenticate to the OCI Artifact source, optional
AuthProvider runtime.RawExtension `json:"authProvider,omitempty"`
}
2 changes: 2 additions & 0 deletions api/v1alpha1/store_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ type StoreSpec struct {
Name string `json:"name,omitempty"`
// Plugin path, optional
Address string `json:"address,omitempty"`
// OCI Artifact source to download the plugin from, optional
Source *PluginSource `json:"source,omitempty"`

// +kubebuilder:pruning:PreserveUnknownFields
// Parameters of the store
Expand Down
3 changes: 3 additions & 0 deletions api/v1alpha1/verifier_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type VerifierSpec struct {
// # Optional. URL/file path
Address string `json:"address,omitempty"`

// OCI Artifact source to download the plugin from, optional
Source *PluginSource `json:"source,omitempty"`

// +kubebuilder:pruning:PreserveUnknownFields
// Parameters for this verifier
Parameters runtime.RawExtension `json:"parameters,omitempty"`
Expand Down
26 changes: 26 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion charts/ratify/crds/store-customresourcedefinition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,22 @@ spec:
description: Parameters of this store
type: object
x-kubernetes-preserve-unknown-fields: true
source:
description: OCI Artifact source to download the plugin from, optional
properties:
artifact:
description: OCI Artifact source to download the plugin from
type: string
authProvider:
description: AuthProvider to use to authenticate to the OCI Artifact
source, optional
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
status:
description: StoreStatus defines the observed state of Store
type: object
type: object
served: true
storage: true
storage: true
14 changes: 13 additions & 1 deletion charts/ratify/crds/verifier-customresourcedefinition.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,22 @@ spec:
description: Parameters of this verifier
type: object
x-kubernetes-preserve-unknown-fields: true
source:
description: OCI Artifact source to download the plugin from, optional
properties:
artifact:
description: OCI Artifact source to download the plugin from
type: string
authProvider:
description: AuthProvider to use to authenticate to the OCI Artifact
source, optional
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
status:
description: VerifierStatus defines the observed state of Verifier
type: object
type: object
served: true
storage: true
storage: true
12 changes: 12 additions & 0 deletions config/crd/bases/config.ratify.deislabs.io_stores.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ spec:
description: Parameters of the store
type: object
x-kubernetes-preserve-unknown-fields: true
source:
description: OCI Artifact source to download the plugin from, optional
properties:
artifact:
description: OCI Artifact source to download the plugin from
type: string
authProvider:
description: AuthProvider to use to authenticate to the OCI Artifact
source, optional
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
status:
description: StoreStatus defines the observed state of Store
Expand Down
12 changes: 12 additions & 0 deletions config/crd/bases/config.ratify.deislabs.io_verifiers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ spec:
description: Parameters for this verifier
type: object
x-kubernetes-preserve-unknown-fields: true
source:
description: OCI Artifact source to download the plugin from, optional
properties:
artifact:
description: OCI Artifact source to download the plugin from
type: string
authProvider:
description: AuthProvider to use to authenticate to the OCI Artifact
source, optional
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
type: object
status:
description: VerifierStatus defines the observed state of Verifier
Expand Down
9 changes: 9 additions & 0 deletions config/samples/config_v1alpha1_verifier_dynamic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: config.ratify.deislabs.io/v1alpha1
kind: Verifier
metadata:
name: verifier-dynamic
spec:
name: dynamic
artifactTypes: application/vnd.ratify.spdx.v0
source:
artifact: wabbitnetworks.azurecr.io/test/sample-verifier-plugin:v1
78 changes: 78 additions & 0 deletions docs/reference/dynamic-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Dynamic Plugins

While Ratify provides a number of built-in referrer stores and verifiers, there may be times that you need to add additional out-of-tree plugins to verify additional artifact types or check for specific conditions. Whether you've followed the [plugin authoring guide](./creating-plugins.md), or you want to use a plugin that's provided by a third party, the next step is to make your plugin available to be called at runtime.

Ratify includes an optional dynamic plugins feature to simplify plugin distribution. This removes the need to rebuild or maintain your own Ratify container image. When enabled, plugins are stored as OCI artifacts and pulled down at runtime when they are registered via CRD. This guide will show you how to activate and configure dynamic plugins.

## Uploading your plugin

Upload your plugin to a registry that supports OCI artifacts. Here we're using the sample plugin located at `plugins/verifier/sample`. Replace the registry values with your own.

```shell
CGO_ENABLED=0 go build -o=./sample ./plugins/verifier/sample
oras push myregistry.azurecr.io/sample-plugin:v1 ./sample
```

> It's important to build plugins with `CGO_ENABLED=0` so that they can run inside the Ratify [distroless](https://github.com/GoogleContainerTools/distroless) container
## Ratify Configuration

Now that you have a plugin available as an OCI artifact, it's time to enable the `RATIFY_DYNAMIC_PLUGINS` [feature flag](/docs/reference/usage.md#feature-flags). Here, we enable it via Helm chart parameter:

```shell
# Option 1: to enable on a fresh install
helm install ratify \
ratify/ratify --atomic \
--set-file provider.tls.crt=${CERT_DIR}/server.crt \
--set-file provider.tls.key=${CERT_DIR}/server.key \
--set provider.tls.cabundle="$(cat ${CERT_DIR}/ca.crt | base64 | tr -d '\n')" \
--set featureFlags.RATIFY_DYNAMIC_PLUGINS=true

# Option 2: to enable on a previously-installed release
helm upgrade ratify \
ratify/ratify --atomic \
--reuse-values \
--set featureFlags.RATIFY_DYNAMIC_PLUGINS=true
```

## Plugin Configuration

The last step is to specify the optional `source` property to tell Ratify where to download the plugin from. Dynamic plugins use the same [auth providers](/docs/reference/oras-auth-provider.md) and options as the builtin ORAS store (ex: `azureWorkloadIdentity`, `awsEcrBasic`, `k8Secrets`) for authentication to the registry where your plugins are located.

```yaml
apiVersion: config.ratify.deislabs.io/v1alpha1
kind: Verifier
metadata:
name: verifier-sample
spec:
name: sample
artifactTypes: application/vnd.ratify.spdx.v0
source:
artifact: myregistry.azurecr.io/sample-plugin:v1
authProvider:
name: azureWorkloadIdentity
```
## Confirmation / Troubleshooting
You can check the Ratify logs for more details on which plugin(s) were downloaded. Your specific commands may vary slightly based on the values you provided during chart installation.
```shell
kubectl logs -n gatekeeper-system deployment/ratify
```

This will generate output similar to below, which can be used for confirmation of a successful plugin download or to aid in troubleshooting.

```text
time="2023-01-18T16:44:46Z" level=info msg="Setting log level to info"
time="2023-01-18T16:44:46Z" level=info msg="Feature flag DYNAMIC_PLUGINS is enabled"
time="2023-01-18T16:44:46Z" level=info msg="starting crd manager"
time="2023-01-18T16:44:46Z" level=info msg="initializing executor with config file at default config path"
<snip>
time="2023-01-18T16:44:46Z" level=info msg="reconciling verifier 'verifier-dynamic'"
time="2023-01-18T16:44:46Z" level=info msg="Address was empty, setting to default path: /.ratify/plugins"
time="2023-01-18T16:44:47Z" level=info msg="selected auth provider: azureWorkloadIdentity"
time="2023-01-18T16:44:48Z" level=info msg="downloaded verifier plugin dynamic from myregistry.azurecr.io/sample-plugin:v1 to /.ratify/plugins/dynamic"
time="2023-01-18T16:44:48Z" level=info msg="verifier 'dynamic' added to verifier map"
<snip>
```
2 changes: 2 additions & 0 deletions docs/reference/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ This page documents useful flags and options supported by Ratify

Ratify may roll out new features behind feature flags, which are activated by setting the corresponding environment variable `RATIFY_<FEATURE_NAME>=1`.
A value of `1` indicates the feature is active; any other value disables the flag.

- `RATIFY_DYNAMIC_PLUGINS`: (disabled) Enables Ratify to download plugins at runtime from an OCI registry by setting `source` on the plugin config
2 changes: 1 addition & 1 deletion httpserver/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ ARG RATIFY_FOLDER=$HOME/.ratify/
WORKDIR /

COPY --from=builder /app/out/ratify /app/
COPY --from=builder /app/out/plugins ${RATIFY_FOLDER}/plugins
COPY --from=builder --chown=65532:65532 /app/out/plugins ${RATIFY_FOLDER}/plugins
COPY --from=builder /app/config/config.json ${RATIFY_FOLDER}

ENV RATIFY_CONFIG=${RATIFY_FOLDER}
Expand Down
Loading

0 comments on commit 1e69abe

Please sign in to comment.