Skip to content

fix: image registries not handling CA certificates #729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 21, 2024
Merged
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
5 changes: 5 additions & 0 deletions api/v1alpha1/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const (
// ServiceLoadBalancerVariableName is the Service LoadBalancer config patch variable name.
ServiceLoadBalancerVariableName = "serviceLoadBalancer"

// GlobalMirrorVariableName is the global image registry mirror patch variable name.
GlobalMirrorVariableName = "globalImageRegistryMirror"
// ImageRegistriesVariableName is the image registries patch variable name.
ImageRegistriesVariableName = "imageRegistries"

// NamespaceSyncLabelKey is a label that can be applied to a namespace.
//
// When a namespace has a label with this key, ClusterClasses and their Templates are
Expand Down
6 changes: 2 additions & 4 deletions api/v1alpha1/zz_generated.deepcopy.go

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

19 changes: 18 additions & 1 deletion docs/content/customization/generic/image-registries.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,24 @@ kubectl create secret generic my-registry-credentials \
--from-literal username=${REGISTRY_USERNAME} --from-literal password=${REGISTRY_PASSWORD}
```

To add image registry credentials, specify the following configuration:
If your registry requires a private or self-signed CA certificate,
create a Kubernetes Secret with the `ca.crt` key populated with the CA certificate in PEM format:

```shell
kubectl create secret generic my-mirror-ca-cert \
--from-file=ca.crt=registry-ca.crt
```

To set both image registry credentials and CA certificate,
create a Kubernetes Secret with keys for `username`, `password`, and `ca.crt`:

```shell
kubectl create secret generic my-registry-credentials \
--from-literal username=${REGISTRY_USERNAME} --from-literal password=${REGISTRY_PASSWORD} \
--from-file=ca.crt=registry-ca.crt
```

To add image registry credentials and/or CA certificate, specify the following configuration:

```yaml
apiVersion: cluster.x-k8s.io/v1beta1
Expand Down
8 changes: 0 additions & 8 deletions pkg/handlers/generic/mutation/imageregistries/constants.go

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ func templateFilesForImageCredentialProviderConfigs(
files = append(files, *kubeletCredentialProviderConfigFile)
}

kubeletDynamicCredentialProviderConfigFile, err := templateDynamicCredentialProviderConfig(configs)
kubeletDynamicCredentialProviderConfigFile, err := templateDynamicCredentialProviderConfig(
configs,
)
if err != nil {
return nil, err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"errors"
"fmt"

corev1 "k8s.io/api/core/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -26,8 +25,6 @@ import (
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/patches/selectors"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/variables"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/k8s/client"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/imageregistries"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/mirrors"
handlersutils "github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/utils"
)

Expand All @@ -46,7 +43,7 @@ func NewPatch(
return newImageRegistriesPatchHandler(
cl,
v1alpha1.ClusterConfigVariableName,
imageregistries.VariableName,
v1alpha1.ImageRegistriesVariableName,
)
}

Expand Down Expand Up @@ -87,12 +84,12 @@ func (h *imageRegistriesPatchHandler) Mutate(
globalMirror, globalMirrorErr := variables.Get[v1alpha1.GlobalImageRegistryMirror](
vars,
h.variableName,
mirrors.GlobalMirrorVariableName,
v1alpha1.GlobalMirrorVariableName,
)

switch {
case variables.IsNotFoundError(imageRegistriesErr) && variables.IsNotFoundError(globalMirrorErr):
log.V(5).Info("Image Registry Credentials variable not defined")
log.V(5).Info("Image Registry Credentials and Global Registry Mirror variable not defined")
return nil
case imageRegistriesErr != nil && !variables.IsNotFoundError(imageRegistriesErr):
return imageRegistriesErr
Expand Down Expand Up @@ -287,7 +284,7 @@ func ensureOwnerReferenceOnCredentialsSecrets(
}

for _, credential := range credentials {
if secretName := secretNameForImageRegistryCredentials(credential); secretName != "" {
if secretName := handlersutils.SecretNameForImageRegistryCredentials(credential); secretName != "" {
// Ensure the Secret is owned by the Cluster so it is correctly moved and deleted with the Cluster.
// This code assumes that Secret exists and that was validated before calling this function.
err := handlersutils.EnsureOwnerReferenceForSecret(
Expand Down Expand Up @@ -317,7 +314,7 @@ func registryWithOptionalCredentialsFromImageRegistryCredentials(
registryWithOptionalCredentials := providerConfig{
URL: imageRegistry.URL,
}
secret, err := secretForImageRegistryCredentials(
secret, err := handlersutils.SecretForImageRegistryCredentials(
ctx,
c,
imageRegistry.Credentials,
Expand Down Expand Up @@ -350,7 +347,7 @@ func mirrorConfigFromGlobalImageRegistryMirror(
URL: mirror.URL,
Mirror: true,
}
secret, err := secretForImageRegistryCredentials(
secret, err := handlersutils.SecretForImageRegistryCredentials(
ctx,
c,
mirror.Credentials,
Expand Down Expand Up @@ -438,28 +435,6 @@ func createSecretIfNeeded(
return nil
}

// secretForImageRegistryCredentials returns the Secret for the given ImageRegistryCredentials.
// Returns nil if the secret field is empty.
func secretForImageRegistryCredentials(
ctx context.Context,
c ctrlclient.Reader,
credentials *v1alpha1.RegistryCredentials,
objectNamespace string,
) (*corev1.Secret, error) {
name := secretNameForImageRegistryCredentials(credentials)
if name == "" {
return nil, nil
}

key := ctrlclient.ObjectKey{
Name: name,
Namespace: objectNamespace,
}
secret := &corev1.Secret{}
err := c.Get(ctx, key, secret)
return secret, err
}

// This handler reads input from two user provided variables: globalImageRegistryMirror and imageRegistries.
// We expect if imageRegistries is set it will either have static credentials
// or be for a registry where the credential plugin returns the credentials, ie ECR, GCR, ACR, etc,
Expand Down Expand Up @@ -491,12 +466,3 @@ func needImageRegistryCredentialsConfiguration(configs []providerConfig) (bool,

return true, nil
}

// secretForImageRegistryCredentials returns the name of the Secret for the given RegistryCredentials.
// Returns an empty string if the credentials or secret field is empty.
func secretNameForImageRegistryCredentials(credentials *v1alpha1.RegistryCredentials) string {
if credentials == nil || credentials.SecretRef == nil || credentials.SecretRef.Name == "" {
return ""
}
return credentials.SecretRef.Name
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers/mutation"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/testutils/capitest"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/common/pkg/testutils/capitest/request"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/pkg/handlers/generic/mutation/imageregistries"
"github.com/nutanix-cloud-native/cluster-api-runtime-extensions-nutanix/test/helpers"
)

Expand Down Expand Up @@ -161,7 +160,7 @@ var _ = Describe("Generate Image registry patches", func() {
[]v1alpha1.ImageRegistry{{
URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com",
}},
imageregistries.VariableName,
v1alpha1.ImageRegistriesVariableName,
),
},
RequestItem: request.NewKubeadmControlPlaneTemplateRequestItem(""),
Expand Down Expand Up @@ -221,7 +220,7 @@ var _ = Describe("Generate Image registry patches", func() {
},
},
}},
imageregistries.VariableName,
v1alpha1.ImageRegistriesVariableName,
),
},
RequestItem: request.NewKubeadmControlPlaneTemplateRequest(
Expand Down Expand Up @@ -283,7 +282,7 @@ var _ = Describe("Generate Image registry patches", func() {
[]v1alpha1.ImageRegistry{{
URL: "https://123456789.dkr.ecr.us-east-1.amazonaws.com",
}},
imageregistries.VariableName,
v1alpha1.ImageRegistriesVariableName,
),
capitest.VariableWithValue(
"builtin",
Expand Down Expand Up @@ -343,7 +342,7 @@ var _ = Describe("Generate Image registry patches", func() {
},
},
}},
imageregistries.VariableName,
v1alpha1.ImageRegistriesVariableName,
),
capitest.VariableWithValue(
"builtin",
Expand Down Expand Up @@ -405,7 +404,7 @@ var _ = Describe("Generate Image registry patches", func() {
[]v1alpha1.ImageRegistry{{
URL: "https://registry.example.com",
}},
imageregistries.VariableName,
v1alpha1.ImageRegistriesVariableName,
),
},
RequestItem: request.NewKubeadmControlPlaneTemplateRequestItem(""),
Expand Down
8 changes: 0 additions & 8 deletions pkg/handlers/generic/mutation/mirrors/constants.go

This file was deleted.

Loading
Loading