Skip to content

Commit

Permalink
MGMT-16508: Add API to AgentServiceConfig CRD to allow pass of CA cer…
Browse files Browse the repository at this point in the history
…tificates for image pull. (#5884)

This PR introduces a new field to the AgentServiceConfig CRD `imagePullCAConfigMap` which is a LocalObjectReference to a config map containing CA certificates
These certificates are to be used by the image service for the purpose of verifying the CA of HTTPS connections used for pulling images.

`imagePullConfigMap` is expected to reference a ConfigMap containing a single file `extra-ca.pem` which contains the CA certificate.
If multiple CA certificates are to be used, the user is expected to append these into the same PEM.

This code also passes the path `ADDITIONAL_CA_FILE` to the image service if the additional CA file is present.

This code sets up the Volume for this and maps to either an empty directory or maps the content of the ConfigMap.

This will ensure that the CA's will be available for use by the image service.
  • Loading branch information
paul-maidment committed Jan 30, 2024
1 parent 7dbb3b1 commit 268d4ed
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 3 deletions.
8 changes: 8 additions & 0 deletions api/v1beta1/agentserviceconfig_types.go
Expand Up @@ -109,6 +109,12 @@ type AgentServiceConfigSpec struct {
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="List of container registries without authentication"
// +optional
UnauthenticatedRegistries []string `json:"unauthenticatedRegistries,omitempty"`
// OSImageCACertRef is a reference to a config map containing a certificate authority certificate
// this is an optional certificate to allow a user to add a certificate authority for a HTTPS source of images
// this certificate will be used by the assisted-image-service when pulling OS images.
//+operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OS Image CA Cert ConfigMap reference"
// +optional
OSImageCACertRef *corev1.LocalObjectReference `json:"OSImageCACertRef,omitempty"`
}

// ConditionType related to our reconcile loop in addition to all the reasons
Expand Down Expand Up @@ -181,6 +187,8 @@ const (
ReasonSpokeClientCreationFailure string = "ReasonSpokeClientCreationFailure"
// ReasonKonnectivityAgentFailure when there was a failure creating the namespace.
ReasonKonnectivityAgentFailure string = "KonnectivityAgentFailure"
// ReasonOSImageCACertRefFailure when there has been a failure resolving the OS image CA using OSImageCACertRef.
ReasonOSImageCACertRefFailure string = "OSImageCACertRefFailure"

// IPXEHTTPRouteEnabled is expected value in IPXEHTTPRoute to enable the route
IPXEHTTPRouteEnabled string = "enabled"
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

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

Expand Up @@ -38,6 +38,18 @@ spec:
spec:
description: AgentServiceConfigSpec defines the desired state of AgentServiceConfig.
properties:
OSImageCACertRef:
description: OSImageCACertRef is a reference to a config map containing
a certificate authority certificate this is an optional certificate
to allow a user to add a certificate authority for a HTTPS source
of images this certificate will be used by the assisted-image-service
when pulling OS images.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
databaseStorage:
description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the
Expand Down
Expand Up @@ -41,6 +41,18 @@ spec:
description: HypershiftAgentServiceConfigSpec defines the desired state
of HypershiftAgentServiceConfig.
properties:
OSImageCACertRef:
description: OSImageCACertRef is a reference to a config map containing
a certificate authority certificate this is an optional certificate
to allow a user to add a certificate authority for a HTTPS source
of images this certificate will be used by the assisted-image-service
when pulling OS images.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
databaseStorage:
description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the
Expand Down
24 changes: 24 additions & 0 deletions config/crd/resources.yaml
Expand Up @@ -1135,6 +1135,18 @@ spec:
spec:
description: AgentServiceConfigSpec defines the desired state of AgentServiceConfig.
properties:
OSImageCACertRef:
description: OSImageCACertRef is a reference to a config map containing
a certificate authority certificate this is an optional certificate
to allow a user to add a certificate authority for a HTTPS source
of images this certificate will be used by the assisted-image-service
when pulling OS images.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
databaseStorage:
description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the
Expand Down Expand Up @@ -1806,6 +1818,18 @@ spec:
description: HypershiftAgentServiceConfigSpec defines the desired state
of HypershiftAgentServiceConfig.
properties:
OSImageCACertRef:
description: OSImageCACertRef is a reference to a config map containing
a certificate authority certificate this is an optional certificate
to allow a user to add a certificate authority for a HTTPS source
of images this certificate will be used by the assisted-image-service
when pulling OS images.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
databaseStorage:
description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the
Expand Down
Expand Up @@ -27,6 +27,12 @@ spec:
kind: AgentServiceConfig
name: agentserviceconfigs.agent-install.openshift.io
specDescriptors:
- description: OSImageCACertRef is a reference to a config map containing a
certificate authority certificate this is an optional certificate to allow
a user to add a certificate authority for a HTTPS source of images this
certificate will be used by the assisted-image-service when pulling OS images.
displayName: OS Image CA Cert ConfigMap reference
path: OSImageCACertRef
- description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the resource
requests, minimum 10GiB is recommended.
Expand Down
Expand Up @@ -36,6 +36,18 @@ spec:
spec:
description: AgentServiceConfigSpec defines the desired state of AgentServiceConfig.
properties:
OSImageCACertRef:
description: OSImageCACertRef is a reference to a config map containing
a certificate authority certificate this is an optional certificate
to allow a user to add a certificate authority for a HTTPS source
of images this certificate will be used by the assisted-image-service
when pulling OS images.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
databaseStorage:
description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the
Expand Down
Expand Up @@ -39,6 +39,18 @@ spec:
description: HypershiftAgentServiceConfigSpec defines the desired state
of HypershiftAgentServiceConfig.
properties:
OSImageCACertRef:
description: OSImageCACertRef is a reference to a config map containing
a certificate authority certificate this is an optional certificate
to allow a user to add a certificate authority for a HTTPS source
of images this certificate will be used by the assisted-image-service
when pulling OS images.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
databaseStorage:
description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the
Expand Down
Expand Up @@ -235,6 +235,12 @@ spec:
kind: AgentServiceConfig
name: agentserviceconfigs.agent-install.openshift.io
specDescriptors:
- description: OSImageCACertRef is a reference to a config map containing a
certificate authority certificate this is an optional certificate to allow
a user to add a certificate authority for a HTTPS source of images this
certificate will be used by the assisted-image-service when pulling OS images.
displayName: OS Image CA Cert ConfigMap reference
path: OSImageCACertRef
- description: DatabaseStorage defines the spec of the PersistentVolumeClaim
to be created for the database's filesystem. With respect to the resource
requests, minimum 10GiB is recommended.
Expand Down
68 changes: 65 additions & 3 deletions internal/controller/controllers/agentserviceconfig_controller.go
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"

"github.com/go-openapi/swag"
Expand Down Expand Up @@ -84,13 +85,15 @@ const (
assistedConfigHashAnnotation = "agent-install.openshift.io/config-hash"
mirrorConfigHashAnnotation = "agent-install.openshift.io/mirror-hash"
userConfigHashAnnotation = "agent-install.openshift.io/user-config-hash"
osImagesCAConfigHashAnnotation = "agent-install.openshift.io/os-images-ca-hash"
imageServiceStatefulSetFinalizerName = imageServiceName + "." + aiv1beta1.Group + "/ai-deprovision"
agentServiceConfigFinalizerName = "agentserviceconfig." + aiv1beta1.Group + "/ai-deprovision"

servingCertAnnotation = "service.beta.openshift.io/serving-cert-secret-name"
injectCABundleAnnotation = "service.beta.openshift.io/inject-cabundle"

defaultNamespace = "default"
defaultNamespace = "default"
osImageDownloadTrustedCAFilename = "tls.crt"
)

var (
Expand Down Expand Up @@ -1238,8 +1241,6 @@ func newImageServiceStatefulSet(ctx context.Context, log logrus.FieldLogger, asc

var replicas int32 = 1
statefulSet.Spec.Replicas = &replicas

statefulSet.Spec.Template.Spec.Containers = []corev1.Container{container}
statefulSet.Spec.Template.Spec.ServiceAccountName = imageServiceName

volumes := ensureVolume(statefulSet.Spec.Template.Spec.Volumes, corev1.Volume{
Expand All @@ -1261,6 +1262,34 @@ func newImageServiceStatefulSet(ctx context.Context, log logrus.FieldLogger, asc
},
})

if asc.spec.OSImageCACertRef != nil {
cm := &corev1.ConfigMap{}
namespacedName := types.NamespacedName{Name: asc.spec.OSImageCACertRef.Name, Namespace: asc.namespace}
err := asc.Client.Get(ctx, namespacedName, cm)
if err != nil {
return err
}
osImagesCAConfigHash, err := checksumMap(cm.Data)
if err != nil {
return err
}
setAnnotation(&statefulSet.ObjectMeta, osImagesCAConfigHashAnnotation, osImagesCAConfigHash)
container.Env = append(container.Env, corev1.EnvVar{Name: "OS_IMAGE_DOWNLOAD_TRUSTED_CA_FILE", Value: filepath.Join("/etc/image-service/os-images-ca-bundle", osImageDownloadTrustedCAFilename)})
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{Name: "os-images-ca-bundle", MountPath: "/etc/image-service/os-images-ca-bundle"})
volumes = ensureVolume(volumes, corev1.Volume{
Name: "os-images-ca-bundle",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: asc.spec.OSImageCACertRef.Name,
},
},
},
})
}

statefulSet.Spec.Template.Spec.Containers = []corev1.Container{container}

if asc.spec.ImageStorage != nil {
var found bool
for i, claim := range statefulSet.Spec.VolumeClaimTemplates {
Expand Down Expand Up @@ -2356,7 +2385,40 @@ func getImageService(ctx context.Context, log logrus.FieldLogger, asc ASC) strin
return imageServiceURL
}

func registerCACertFailureCondition(ctx context.Context, log logrus.FieldLogger, err error, asc ASC) error {
conditionsv1.SetStatusConditionNoHeartbeat(
asc.conditions, conditionsv1.Condition{
Type: aiv1beta1.ConditionReconcileCompleted,
Status: corev1.ConditionTrue,
Reason: aiv1beta1.ReasonOSImageCACertRefFailure,
Message: err.Error(),
},
)
err = asc.Client.Status().Update(ctx, asc.Object)
if err != nil {
log.Errorf("Unable to update status of ASC while attempting to set condition failure for condition %s", aiv1beta1.ConditionReconcileCompleted)
return err
}
return nil
}

func validate(ctx context.Context, log logrus.FieldLogger, asc ASC) (bool, error) {
if asc.spec.OSImageCACertRef != nil && asc.spec.OSImageCACertRef.Name != "" {
osImageCACertConfigMap := &corev1.ConfigMap{}
err := asc.Client.Get(ctx, types.NamespacedName{
Name: asc.spec.OSImageCACertRef.Name,
Namespace: asc.namespace,
}, osImageCACertConfigMap)
if err != nil {
return false, registerCACertFailureCondition(ctx, log, err, asc)
}
_, ok := osImageCACertConfigMap.Data[osImageDownloadTrustedCAFilename]
if !ok || len(osImageCACertConfigMap.Data) != 1 {
err = fmt.Errorf("ConfigMap referenced by OSImgaeCACertRef is expected to contain a single key named \"%s\"", osImageDownloadTrustedCAFilename)
return false, registerCACertFailureCondition(ctx, log, err, asc)
}
}

// Validate the storage configuration. If that returns warnings then generate the
// corresponding events. If it returns errors then update the conditions and stop the
// reconciliation.
Expand Down

0 comments on commit 268d4ed

Please sign in to comment.