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.

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 22, 2024
1 parent 2f45852 commit 048de5a
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 2 deletions.
8 changes: 8 additions & 0 deletions api/v1beta1/agentserviceconfig_types.go
Original file line number Diff line number Diff line change
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"`
// OSImageCACertConfigMapRef 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
OSImageCACertConfigMapRef *corev1.LocalObjectReference `json:"osImageCACertConfigMap,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.

Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,18 @@ spec:
- url
type: object
type: array
osImageCACertConfigMap:
description: OSImageCACertConfigMapRef 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
osImages:
description: OSImages defines a collection of Operating System images
(ie. RHCOS images) that the assisted-service should use as the base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,18 @@ spec:
- url
type: object
type: array
osImageCACertConfigMap:
description: OSImageCACertConfigMapRef 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
osImages:
description: OSImages defines a collection of Operating System images
(ie. RHCOS images) that the assisted-service should use as the base
Expand Down
24 changes: 24 additions & 0 deletions config/crd/resources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,18 @@ spec:
- url
type: object
type: array
osImageCACertConfigMap:
description: OSImageCACertConfigMapRef 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
osImages:
description: OSImages defines a collection of Operating System images
(ie. RHCOS images) that the assisted-service should use as the base
Expand Down Expand Up @@ -2356,6 +2368,18 @@ spec:
- url
type: object
type: array
osImageCACertConfigMap:
description: OSImageCACertConfigMapRef 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
osImages:
description: OSImages defines a collection of Operating System images
(ie. RHCOS images) that the assisted-service should use as the base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ spec:
images that are used if one the operators fails to be successfully deployed
displayName: Must-Gather Images
path: mustGatherImages
- description: OSImageCACertConfigMapRef 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: osImageCACertConfigMap
- description: OSImages defines a collection of Operating System images (ie.
RHCOS images) that the assisted-service should use as the base when generating
discovery ISOs.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,18 @@ spec:
- url
type: object
type: array
osImageCACertConfigMap:
description: OSImageCACertConfigMapRef 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
osImages:
description: OSImages defines a collection of Operating System images
(ie. RHCOS images) that the assisted-service should use as the base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,18 @@ spec:
- url
type: object
type: array
osImageCACertConfigMap:
description: OSImageCACertConfigMapRef 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
osImages:
description: OSImages defines a collection of Operating System images
(ie. RHCOS images) that the assisted-service should use as the base
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ spec:
images that are used if one the operators fails to be successfully deployed
displayName: Must-Gather Images
path: mustGatherImages
- description: OSImageCACertConfigMapRef 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: osImageCACertConfigMap
- description: OSImages defines a collection of Operating System images (ie.
RHCOS images) that the assisted-service should use as the base when generating
discovery ISOs.
Expand Down
58 changes: 56 additions & 2 deletions internal/controller/controllers/agentserviceconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strings"

"github.com/go-openapi/swag"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-version"
routev1 "github.com/openshift/api/route/v1"
aiv1beta1 "github.com/openshift/assisted-service/api/v1beta1"
Expand Down Expand Up @@ -1238,8 +1239,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 +1260,23 @@ func newImageServiceStatefulSet(ctx context.Context, log logrus.FieldLogger, asc
},
})

if asc.spec.OSImageCACertConfigMapRef != nil {
container.Env = append(container.Env, corev1.EnvVar{Name: "OS_IMAGE_DOWNLOAD_TRUSTED_CA_FILE", Value: "/etc/image-service/os-images-ca-bundle/extra-ca.pem"})
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.OSImageCACertConfigMapRef.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 @@ -2357,6 +2373,44 @@ func getImageService(ctx context.Context, log logrus.FieldLogger, asc ASC) strin
}

func validate(ctx context.Context, log logrus.FieldLogger, asc ASC) (bool, error) {

if asc.spec.OSImageCACertConfigMapRef != nil && asc.spec.OSImageCACertConfigMapRef.Name != "" {
var multiErr *multierror.Error
osImageCACertConfigMap := &corev1.ConfigMap{}
key := types.NamespacedName{
Name: asc.spec.OSImageCACertConfigMapRef.Name,
Namespace: asc.namespace,
}
// Retrieve the image pull config map
multiErr = multierror.Append(multiErr, asc.Client.Get(ctx, key, osImageCACertConfigMap))
if len(multiErr.Errors) == 0 {
_, ok := osImageCACertConfigMap.Data["extra-ca.pem"]
if !ok {
multiErr = multierror.Append(multiErr, fmt.Errorf("expected to find single file `extra-ca.pem` in the ConfigMap %s but it was not found", asc.spec.OSImageCACertConfigMapRef.Name))
}
if len(osImageCACertConfigMap.Data) != 1 {
multiErr = multierror.Append(multiErr, fmt.Errorf("found multiple files in ConfigMap %s, a single file was expected but %d files were found", asc.spec.OSImageCACertConfigMapRef.Name, len(osImageCACertConfigMap.Data)))
}
}
if len(multiErr.Errors) > 0 {
// If we detected any errors, set the condition
conditionsv1.SetStatusConditionNoHeartbeat(
asc.conditions, conditionsv1.Condition{
Type: aiv1beta1.ConditionReconcileCompleted,
Status: corev1.ConditionTrue,
Reason: aiv1beta1.ReasonOSImageCACertRefFailure,
Message: multiErr.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 false, err
}
return false, nil
}
}

// 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
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ var _ = Describe("Agent service config controller storage validation", func() {
})

When("Objects haven't been created", func() {

It("Rejects small database storage", func() {
subject.Spec.DatabaseStorage.Resources.Requests = corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse("1Mi"),
Expand Down

0 comments on commit 048de5a

Please sign in to comment.