Skip to content

Commit

Permalink
Add support to integrate Pulp with LDAP
Browse files Browse the repository at this point in the history
This PR depends on pulp/pulp-oci-images#531.
There is also a possible issue in the integration between Pulp and
LDAPS/LDAP+TLS using `django-auth-ldap`.
While we don't find a solution, I could workaround the exceptions using:
```
FROM quay.io/pulp/pulp-minimal:3.32
RUN pip3 install django-auth-ldap==4.5.0
RUN sed -i '126i \            if options != None:' /usr/local/lib/python3.8/site-packages/django_auth_ldap/backend.py
RUN sed -i '127i \                options = {int(k):v for k,v in options.items()}' /usr/local/lib/python3.8/site-packages/django_auth_ldap/backend.py
RUN sed -i '859i \                optInt = int(opt)' /usr/local/lib/python3.8/site-packages/django_auth_ldap/backend.py
RUN sed -i '860s/opt, value/optInt, value/' /usr/local/lib/python3.8/site-packages/django_auth_ldap/backend.py
```

closes: #1042
  • Loading branch information
git-hyagi committed Sep 11, 2023
1 parent 017dc71 commit 9a492ea
Show file tree
Hide file tree
Showing 23 changed files with 599 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGES/1042.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added support to configure LDAP with Pulp.
26 changes: 25 additions & 1 deletion apis/repo-manager.pulpproject.org/v1beta2/pulp_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ type PulpSpec struct {
// Job to run django migrations
MigrationJob PulpJob `json:"migration_job,omitempty"`

// Disable database migrations. Useful for situations in which we don't want
// to automatically run the database migrations, for example, during restore.
// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:hidden"}
DisableMigrations bool `json:"disable_migrations,omitempty"`

// Name of the Secret to provide Django cryptographic signing.
// Default: "pulp-secret-key"
// +kubebuilder:validation:Optional
Expand All @@ -358,6 +364,10 @@ type PulpSpec struct {
// Telemetry defines the OpenTelemetry configuration
// +kubebuilder:validation:Optional
Telemetry Telemetry `json:"telemetry,omitempty"`

// LDAP defines the ldap resources used by pulpcore containers to integrate Pulp with LDAP authentication
// +kubebuilder:validation:Optional
LDAP LDAP `json:"ldap,omitempty"`
}

// Api defines desired state of pulpcore-api resources
Expand Down Expand Up @@ -859,6 +869,20 @@ type PulpJob struct {
PulpContainer PulpContainer `json:"container,omitempty"`
}

// LDAP defines the ldap resources used by pulpcore containers to integrate Pulp with LDAP authentication
type LDAP struct {

// The name of the Secret with ldap config.
// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"}
Config string `json:"config,omitempty"`

// The name of the Secret with the CA chain to connect to ldap server.
// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"}
CA string `json:"ca,omitempty"`
}

// PulpStatus defines the observed state of Pulp
type PulpStatus struct {
//+operator-sdk:csv:customresourcedefinitions:type=status,xDescriptors={"urn:alm:descriptor:io.kubernetes.conditions"}
Expand Down Expand Up @@ -893,11 +917,11 @@ type PulpStatus struct {
LastDeploymentUpdate string `json:"last_deployment_update,omitempty"`
}

// Pulp is the Schema for the pulps API
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
//+kubebuilder:storageversion

// Pulp is the Schema for the pulps API
type Pulp struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Expand Down
16 changes: 16 additions & 0 deletions apis/repo-manager.pulpproject.org/v1beta2/zz_generated.deepcopy.go

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

22 changes: 20 additions & 2 deletions bundle/manifests/pulp-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ metadata:
capabilities: Full Lifecycle
categories: Integration & Delivery
containerImage: quay.io/pulp/pulp-operator:devel
createdAt: "2023-09-05T18:55:57Z"
createdAt: "2023-09-08T21:28:56Z"
description: Pulp is a platform for managing repositories of software packages
and making them available to a large number of consumers.
operators.operatorframework.io/builder: operator-sdk-v1.29.0
Expand Down Expand Up @@ -277,7 +277,8 @@ spec:
- displayName: Postgres Secret
path: postgres_secret
version: v1beta2
- displayName: Pulp
- description: Pulp is the Schema for the pulps API
displayName: Pulp
kind: Pulp
name: pulps.repo-manager.pulpproject.org
specDescriptors:
Expand Down Expand Up @@ -695,6 +696,13 @@ spec:
path: deployment_type
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: Disable database migrations. Useful for situations in which we
don't want to automatically run the database migrations, for example, during
restore.
displayName: Disable Migrations
path: disable_migrations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: 'Name of the ConfigMap with the list of Execution Environments
that should be synchronized. Default: ee-default-images'
displayName: EEDefaults
Expand Down Expand Up @@ -809,6 +817,16 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:ingress_type:Ingress
- description: The name of the Secret with the CA chain to connect to ldap server.
displayName: CA
path: ldap.ca
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- description: The name of the Secret with ldap config.
displayName: Config
path: ldap.config
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- description: Port exposed by pulp-web service when ingress_type==loadbalancer
displayName: Loadbalancer Port
path: loadbalancer_port
Expand Down
18 changes: 18 additions & 0 deletions bundle/manifests/repo-manager.pulpproject.org_pulps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ spec:
- name: v1beta2
schema:
openAPIV3Schema:
description: Pulp is the Schema for the pulps API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
Expand Down Expand Up @@ -6118,6 +6119,11 @@ spec:
- pulp
- galaxy
type: string
disable_migrations:
description: Disable database migrations. Useful for situations in
which we don't want to automatically run the database migrations,
for example, during restore.
type: boolean
ee_defaults:
description: 'Name of the ConfigMap with the list of Execution Environments
that should be synchronized. Default: ee-default-images'
Expand Down Expand Up @@ -6214,6 +6220,18 @@ spec:
to grant a ClusterRole (to do a get into the IngressClass and verify
the controller). Default: false'
type: boolean
ldap:
description: LDAP defines the ldap resources used by pulpcore containers
to integrate Pulp with LDAP authentication
properties:
ca:
description: The name of the Secret with the CA chain to connect
to ldap server.
type: string
config:
description: The name of the Secret with ldap config.
type: string
type: object
loadbalancer_port:
description: Port exposed by pulp-web service when ingress_type==loadbalancer
format: int32
Expand Down
18 changes: 18 additions & 0 deletions config/crd/bases/repo-manager.pulpproject.org_pulps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ spec:
- name: v1beta2
schema:
openAPIV3Schema:
description: Pulp is the Schema for the pulps API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
Expand Down Expand Up @@ -6119,6 +6120,11 @@ spec:
- pulp
- galaxy
type: string
disable_migrations:
description: Disable database migrations. Useful for situations in
which we don't want to automatically run the database migrations,
for example, during restore.
type: boolean
ee_defaults:
description: 'Name of the ConfigMap with the list of Execution Environments
that should be synchronized. Default: ee-default-images'
Expand Down Expand Up @@ -6215,6 +6221,18 @@ spec:
to grant a ClusterRole (to do a get into the IngressClass and verify
the controller). Default: false'
type: boolean
ldap:
description: LDAP defines the ldap resources used by pulpcore containers
to integrate Pulp with LDAP authentication
properties:
ca:
description: The name of the Secret with the CA chain to connect
to ldap server.
type: string
config:
description: The name of the Secret with ldap config.
type: string
type: object
loadbalancer_port:
description: Port exposed by pulp-web service when ingress_type==loadbalancer
format: int32
Expand Down
20 changes: 19 additions & 1 deletion config/manifests/bases/pulp-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ spec:
- displayName: Postgres Secret
path: postgres_secret
version: v1beta2
- displayName: Pulp
- description: Pulp is the Schema for the pulps API
displayName: Pulp
kind: Pulp
name: pulps.repo-manager.pulpproject.org
specDescriptors:
Expand Down Expand Up @@ -695,6 +696,13 @@ spec:
path: deployment_type
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: Disable database migrations. Useful for situations in which we
don't want to automatically run the database migrations, for example, during
restore.
displayName: Disable Migrations
path: disable_migrations
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:hidden
- description: 'Name of the ConfigMap with the list of Execution Environments
that should be synchronized. Default: ee-default-images'
displayName: EEDefaults
Expand Down Expand Up @@ -809,6 +817,16 @@ spec:
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:text
- urn:alm:descriptor:com.tectonic.ui:fieldDependency:ingress_type:Ingress
- description: The name of the Secret with the CA chain to connect to ldap server.
displayName: CA
path: ldap.ca
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- description: The name of the Secret with ldap config.
displayName: Config
path: ldap.config
x-descriptors:
- urn:alm:descriptor:com.tectonic.ui:advanced
- description: Port exposed by pulp-web service when ingress_type==loadbalancer
displayName: Loadbalancer Port
path: loadbalancer_port
Expand Down
49 changes: 47 additions & 2 deletions controllers/backup/secret.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package repo_manager_backup

import (
"bytes"
"context"

"gopkg.in/yaml.v3"

repomanagerpulpprojectorgv1beta2 "github.com/pulp/pulp-operator/apis/repo-manager.pulpproject.org/v1beta2"
"github.com/pulp/pulp-operator/controllers"
"gopkg.in/yaml.v3"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/cli-runtime/pkg/printers"
)

// secretType contains all the information needed to make the backup of the secret
Expand Down Expand Up @@ -117,6 +118,21 @@ func (r *RepoManagerBackupReconciler) backupSecret(ctx context.Context, pulpBack
log.Info("SSO secret backup finished")
}

// LDAP CONFIG SECRET
if len(pulp.Spec.LDAP.Config) > 0 {
if err := r.backupLDAPSecret(ctx, secretType{"ldap_secret", pulpBackup, backupDir, "ldap_secret.yaml", pulp.Spec.LDAP.Config, pod}); err != nil {
return err
}
log.Info("LDAP secret backup finished")
}
// LDAP CA SECRET
if len(pulp.Spec.LDAP.CA) > 0 {
if err := r.backupLDAPSecret(ctx, secretType{"ldap_ca_secret", pulpBackup, backupDir, "ldap_ca_secret.yaml", pulp.Spec.LDAP.CA, pod}); err != nil {
return err
}
log.Info("LDAP CA secret backup finished")
}

return nil
}

Expand Down Expand Up @@ -152,3 +168,32 @@ func (r *RepoManagerBackupReconciler) createBackupFile(ctx context.Context, secr
log.Info("Container token secret backup finished")
return nil
}

// backupLDAPSecret stores a copy of the LDAP Secrets in YAML format.
// Since we don't need to keep compatibility with ansible version anymore, this
// method does not need to follow an specific struct and should work with any Secret.
func (r *RepoManagerBackupReconciler) backupLDAPSecret(ctx context.Context, secretType secretType) error {
log := r.RawLogger
secret := &corev1.Secret{}
err := r.Get(ctx, types.NamespacedName{Name: secretType.secretName, Namespace: secretType.pulpBackup.Namespace}, secret)
if err != nil {
log.Error(err, "Error trying to find "+secretType.secretName+" secret")
return err
}

secretYaml := new(bytes.Buffer)
ymlPrinter := printers.YAMLPrinter{}
ymlPrinter.PrintObj(secret, secretYaml)

execCmd := []string{
"bash", "-c", "echo '" + secretYaml.String() + "' > " + secretType.backupDir + "/" + secretType.backupFile,
}
_, err = controllers.ContainerExec(r, secretType.pod, execCmd, secretType.pulpBackup.Name+"-backup-manager", secretType.pod.Namespace)
if err != nil {
log.Error(err, "Failed to backup "+secretType.secretName+" secret")
return err
}

log.Info("LDAP Secret " + secretType.secretName + " backup finished")
return nil
}
44 changes: 44 additions & 0 deletions controllers/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -1007,6 +1008,48 @@ func AddHashLabel(r FunctionResources, deployment *appsv1.Deployment) {
}
}

func (d *CommonDeployment) setLDAPConfigs(resources any) {
pulp := resources.(FunctionResources).Pulp
if len(pulp.Spec.LDAP.CA) == 0 {
return
}

ctx := resources.(FunctionResources).Context
client := resources.(FunctionResources).Client

// add the CA Secret as a volume
volumeName := "ldap-cert"
volume := corev1.Volume{
Name: volumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: pulp.Spec.LDAP.CA,
Items: []corev1.KeyToPath{{
Key: "ca.crt",
Path: "ca.crt",
}},
},
},
}
d.volumes = append(d.volumes, volume)

// retrieve the cert mountPoint from LDAP config Secret
secretName := pulp.Spec.LDAP.Config
secret := &corev1.Secret{}
client.Get(ctx, types.NamespacedName{Name: secretName, Namespace: pulp.Namespace}, secret)
mountPoint := string(secret.Data["auth_ldap_ca_file"])

// mount the CA Secret
volumeMount := corev1.VolumeMount{
Name: volumeName,
MountPath: mountPoint,
SubPath: "ca.crt",
ReadOnly: true,
}
d.volumeMounts = append(d.volumeMounts, volumeMount)

}

// build constructs the fields used in the deployment specification
func (d *CommonDeployment) build(resources any, pulpcoreType string) {
pulp := resources.(FunctionResources).Pulp
Expand All @@ -1030,6 +1073,7 @@ func (d *CommonDeployment) build(resources any, pulpcoreType string) {
d.setInitContainerImage(*pulp, pulpcoreType)
d.setInitContainerVolumeMounts(*pulp)
d.setInitContainerEnvVars(resources)
d.setLDAPConfigs(resources)
d.setInitContainers(*pulp, pulpcoreType)
d.setContainers(*pulp, pulpcoreType)
d.setRestartPolicy()
Expand Down
Loading

0 comments on commit 9a492ea

Please sign in to comment.