Skip to content
Draft
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FROM --platform=$BUILDPLATFORM golang:1.24-alpine@sha256:68932fa6d4d4059845c8f40ad7e654e626f3ebd3706eef7846f319293ab5cb7a AS builder
FROM golang:1.24-alpine@sha256:68932fa6d4d4059845c8f40ad7e654e626f3ebd3706eef7846f319293ab5cb7a AS builder

WORKDIR /app

Expand Down
25 changes: 9 additions & 16 deletions charts/ratify/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,27 +60,20 @@ spec:
seccompProfile:
type: RuntimeDefault
command:
- "/app/ratify"
- "/app/ratify-gatekeeper-provider"
args:
- "serve"
- "--http"
- "-address"
- ":6001"
- "-c"
- "-config"
- "/usr/local/ratify/config.json"
- "--enable-crd-manager"
- --cert-dir=/usr/local/tls
- "-cert-file"
- "/usr/local/tls/tls.crt"
- "-key-file"
- "/usr/local/tls/tls.key"
Comment on lines +65 to +72
{{- if (lookup "v1" "Secret" .Release.Namespace "gatekeeper-webhook-server-cert") }}
- --ca-cert-file=usr/local/tls/client-ca/ca.crt
- "-gatekeeper-ca-cert-file"
- "/usr/local/tls/client-ca/ca.crt"
{{- end }}
- --cache-enabled={{ .Values.provider.cache.enabled }}
- --cache-type={{ default "ristretto" .Values.provider.cache.type }}
- --cache-name={{ default "dapr-redis" .Values.provider.cache.name }}
- --cache-size={{ .Values.provider.cache.cacheSizeMb }}
- --cache-ttl={{ .Values.provider.cache.ttl }}
- --metrics-enabled={{ .Values.instrumentation.metricsEnabled }}
- --metrics-type={{ .Values.instrumentation.metricsType }}
- --metrics-port={{ .Values.instrumentation.metricsPort }}
- --health-port=:{{ .Values.healthPort }}
ports:
- containerPort: 6001
{{- if .Values.instrumentation.metricsEnabled }}
Expand Down
69 changes: 62 additions & 7 deletions internal/store/factory/registrystore/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ import (

"github.com/notaryproject/ratify-go"
"github.com/notaryproject/ratify/v2/internal/store/factory"
provider "github.com/ratify-project/ratify/pkg/common/oras/authprovider"
// Register built-in auth providers so they are available via
// CreateAuthProviderFromConfig. The blank imports trigger each
// package's init() which calls provider.Register().
_ "github.com/ratify-project/ratify/pkg/common/oras/authprovider/azure"
)

const registryStoreType = "registry-store"
Expand Down Expand Up @@ -50,7 +55,14 @@ type options struct {
MaxManifestBytes int64 `json:"max_manifest_bytes,omitempty"`

// Credential is the credential to use when accessing the registry.
// Takes precedence over AuthProvider if both are specified.
Credential credential `json:"credential,omitempty"`

// AuthProvider configures a named auth provider (e.g.
// "azureWorkloadIdentity", "azureManagedIdentity", "dockerConfig")
// to obtain registry credentials dynamically.
// Ignored if Credential is set.
AuthProvider provider.AuthProviderConfig `json:"authProvider,omitempty"`
}

func init() {
Expand All @@ -65,15 +77,29 @@ func init() {
return nil, fmt.Errorf("failed to unmarshal store parameters: %w", err)
}

registryStoreOpts := ratify.RegistryStoreOptions{
PlainHTTP: params.PlainHTTP,
UserAgent: params.UserAgent,
MaxBlobBytes: params.MaxBlobBytes,
MaxManifestBytes: params.MaxManifestBytes,
CredentialProvider: &defaultCredGetter{
var credProvider ratify.RegistryCredentialGetter

// Static credential takes precedence.
if params.Credential.Password != "" {
credProvider = &defaultCredGetter{
username: params.Credential.Username,
password: params.Credential.Password,
},
}
} else if params.AuthProvider != nil {
// Use the named auth provider (azureWorkloadIdentity, etc.)
ap, err := provider.CreateAuthProviderFromConfig(params.AuthProvider)
if err != nil {
return nil, fmt.Errorf("failed to create auth provider: %w", err)
}
credProvider = &authProviderAdapter{provider: ap}
}

registryStoreOpts := ratify.RegistryStoreOptions{
PlainHTTP: params.PlainHTTP,
UserAgent: params.UserAgent,
MaxBlobBytes: params.MaxBlobBytes,
MaxManifestBytes: params.MaxManifestBytes,
CredentialProvider: credProvider,
}

return ratify.NewRegistryStore(registryStoreOpts), nil
Expand All @@ -99,3 +125,32 @@ func (d *defaultCredGetter) Get(_ context.Context, _ string) (ratify.RegistryCre
Password: d.password,
}, nil
}

// authProviderAdapter adapts a v1 [provider.AuthProvider] to the v2
// [ratify.RegistryCredentialGetter] interface, bridging the existing Azure
// Workload Identity, Managed Identity, k8s Secrets, and other auth provider
// implementations into the v2 registry store.
type authProviderAdapter struct {
provider provider.AuthProvider
}

// Get obtains credentials from the underlying auth provider for the given
// server address.
func (a *authProviderAdapter) Get(ctx context.Context, serverAddress string) (ratify.RegistryCredential, error) {
authConfig, err := a.provider.Provide(ctx, serverAddress)
if err != nil {
return ratify.RegistryCredential{}, err
}

// Map v1 AuthConfig fields to v2 RegistryCredential.
// IdentityToken maps to RefreshToken (OAuth2 refresh/identity token).
if authConfig.IdentityToken != "" {
return ratify.RegistryCredential{
RefreshToken: authConfig.IdentityToken,
}, nil
}
return ratify.RegistryCredential{
Username: authConfig.Username,
Password: authConfig.Password,
}, nil
}