- Add jarRef and jarPullSecret fields to FlinkJob CRD (jarUri/basicAuth deprecated) - OCI pull via go-containerregistry with dual auth (K8s pull secret + env vars) - Media type validation on pulled layers - Atomic status patches with runningJarRef/runningJarDigest tracking - NeedsUpgrade/RunningRef/RunningRefPatchData domain helpers - README with usage guide, pushing JARs, and GitHub Actions CI/CD workflow - CONTEXT.md domain glossary
84 lines
2.2 KiB
Go
84 lines
2.2 KiB
Go
package crd
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/google/go-containerregistry/pkg/authn"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
)
|
|
|
|
type dockerConfigJSON struct {
|
|
Auths map[string]authn.AuthConfig `json:"auths"`
|
|
}
|
|
|
|
// ResolveAuth returns an OCI authenticator for the given registry.
|
|
// It checks in order: pull secret from K8s, then environment variables.
|
|
// Returns authn.Anonymous if no credentials are found.
|
|
func (crd *Crd) ResolveAuth(pullSecretName string, server string) (authn.Authenticator, error) {
|
|
if pullSecretName != "" {
|
|
return crd.authFromPullSecret(pullSecretName, server)
|
|
}
|
|
return authFromEnv(server), nil
|
|
}
|
|
|
|
func (crd *Crd) authFromPullSecret(secretName string, server string) (authn.Authenticator, error) {
|
|
ns := os.Getenv("NAMESPACE")
|
|
secret := &corev1.Secret{}
|
|
err := crd.runtimeClient.Get(context.Background(), types.NamespacedName{
|
|
Namespace: ns,
|
|
Name: secretName,
|
|
}, secret)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("reading pull secret %q: %w", secretName, err)
|
|
}
|
|
|
|
if secret.Type != corev1.SecretTypeDockerConfigJson {
|
|
return nil, fmt.Errorf("secret %q is not of type kubernetes.io/dockerconfigjson", secretName)
|
|
}
|
|
|
|
dockerConfigJSONBytes, ok := secret.Data[corev1.DockerConfigJsonKey]
|
|
if !ok {
|
|
return nil, fmt.Errorf("secret %q missing .dockerconfigjson key", secretName)
|
|
}
|
|
|
|
var cfg dockerConfigJSON
|
|
if err := json.Unmarshal(dockerConfigJSONBytes, &cfg); err != nil {
|
|
return nil, fmt.Errorf("parsing docker config from secret %q: %w", secretName, err)
|
|
}
|
|
|
|
if server != "" {
|
|
if entry, ok := cfg.Auths[server]; ok {
|
|
return authn.FromConfig(entry), nil
|
|
}
|
|
}
|
|
|
|
for _, entry := range cfg.Auths {
|
|
return authn.FromConfig(entry), nil
|
|
}
|
|
|
|
return authn.Anonymous, nil
|
|
}
|
|
|
|
func authFromEnv(server string) authn.Authenticator {
|
|
username := os.Getenv("REGISTRY_USERNAME")
|
|
password := os.Getenv("REGISTRY_PASSWORD")
|
|
envServer := os.Getenv("REGISTRY_SERVER")
|
|
|
|
if username == "" || password == "" {
|
|
return authn.Anonymous
|
|
}
|
|
|
|
if envServer != "" && server != "" && envServer != server {
|
|
return authn.Anonymous
|
|
}
|
|
|
|
return authn.FromConfig(authn.AuthConfig{
|
|
Username: username,
|
|
Password: password,
|
|
})
|
|
}
|