Skip to content

Commit

Permalink
Allow customize http vhost config using HttpdCustomization.CustomServ…
Browse files Browse the repository at this point in the history
…iceConfigSecret

This change allows to customize the httpd vhost config using this parameter
to specify a secret that contains service config data. The content of each
provided snippet gets rendered as a go template and placed into
/etc/httpd/conf/httpd_custom_<endpoint>_<key> .
At the end of the vhost config in the default httpd template these custom
configs get included using `Include conf/httpd_custom_<endpoint>_*`.

For information on how sections in httpd configuration get merged, check section
"How the sections are merged" in https://httpd.apache.org/docs/current/sections.html#merging

Depends-On: openstack-k8s-operators/lib-common#591

Signed-off-by: Martin Schuppert <[email protected]>
  • Loading branch information
stuggi committed Jan 10, 2025
1 parent 16c3ed8 commit 3974d63
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 10 deletions.
10 changes: 10 additions & 0 deletions api/bases/keystone.openstack.org_keystoneapis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ spec:
httpdCustomization:
description: HttpdCustomization - customize the httpd service
properties:
customServiceConfigSecret:
description: |-
CustomServiceConfigSecret - customize the httpd vhost config using this parameter to specify
a secret that contains service config data. The content of each provided snippet gets
rendered as a go template and placed into /etc/httpd/conf/httpd_custom_<key> .
In the default httpd template at the end of the vhost those custom configs get
included using `Include conf/httpd_custom_<endpoint>_*`.
For information on how sections in httpd configuration get merged, check section
"How the sections are merged" in https://httpd.apache.org/docs/current/sections.html#merging
type: string
processNumber:
default: 3
description: ProcessNumber - Number of processes running in keystone
Expand Down
2 changes: 2 additions & 0 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,5 @@ require (
// mschuppert: map to latest commit from release-4.16 tag
// must consistent within modules and service operators
replace github.com/openshift/api => github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 //allow-merging

replace github.com/openstack-k8s-operators/lib-common/modules/common => github.com/stuggi/lib-common/modules/common v0.0.0-20250110132704-f4bf5c3b0892
4 changes: 2 additions & 2 deletions api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 h1:J1wuGhVxpsHykZBa6Beb1gQ96Ptej9AE/BvwCBiRj1E=
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20241216113837-d172b3ac0f4e h1:hf4kVQBkyG79WcHBxdQ25QrDBbGFdarebS1Tc0Xclq4=
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20241216113837-d172b3ac0f4e/go.mod h1:YpNTuJhDWhbXM50O3qBkhO7M+OOyRmWkNVmJ4y3cyFs=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20241216113837-d172b3ac0f4e h1:HFo4OqPY0x4ZQeaWI2YGonTXAGTQFt+rOEJlfZVhS7s=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20241216113837-d172b3ac0f4e/go.mod h1:IASoGvp5QM/tBJUd/8i8uIjj4DBnI+64Ydh4r7pmnvA=
github.com/openstack-k8s-operators/lib-common/modules/test v0.5.1-0.20241216113837-d172b3ac0f4e h1:/iWDp3j+ET3gE5IjKHtdZaPd4SQyLHB/4L5jB16cV3I=
Expand All @@ -106,6 +104,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stuggi/lib-common/modules/common v0.0.0-20250110132704-f4bf5c3b0892 h1:nODvJKaxN/T3Lzo/peopLL/UL5fT0aZdQ0XHT/Ql6u4=
github.com/stuggi/lib-common/modules/common v0.0.0-20250110132704-f4bf5c3b0892/go.mod h1:YpNTuJhDWhbXM50O3qBkhO7M+OOyRmWkNVmJ4y3cyFs=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down
10 changes: 10 additions & 0 deletions api/v1beta1/keystoneapi_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,16 @@ type HttpdCustomization struct {
// +kubebuilder:validation:Minimum=1
// ProcessNumber - Number of processes running in keystone API
ProcessNumber *int32 `json:"processNumber"`

// +kubebuilder:validation:Optional
// CustomServiceConfigSecret - customize the httpd vhost config using this parameter to specify
// a secret that contains service config data. The content of each provided snippet gets
// rendered as a go template and placed into /etc/httpd/conf/httpd_custom_<key> .
// In the default httpd template at the end of the vhost those custom configs get
// included using `Include conf/httpd_custom_<endpoint>_*`.
// For information on how sections in httpd configuration get merged, check section
// "How the sections are merged" in https://httpd.apache.org/docs/current/sections.html#merging
CustomServiceConfigSecret *string `json:"customServiceConfigSecret,omitempty"`
}

// KeystoneAPIStatus defines the observed state of KeystoneAPI
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.

10 changes: 10 additions & 0 deletions config/crd/bases/keystone.openstack.org_keystoneapis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ spec:
httpdCustomization:
description: HttpdCustomization - customize the httpd service
properties:
customServiceConfigSecret:
description: |-
CustomServiceConfigSecret - customize the httpd vhost config using this parameter to specify
a secret that contains service config data. The content of each provided snippet gets
rendered as a go template and placed into /etc/httpd/conf/httpd_custom_<key> .
In the default httpd template at the end of the vhost those custom configs get
included using `Include conf/httpd_custom_<endpoint>_*`.
For information on how sections in httpd configuration get merged, check section
"How the sections are merged" in https://httpd.apache.org/docs/current/sections.html#merging
type: string
processNumber:
default: 3
description: ProcessNumber - Number of processes running in keystone
Expand Down
45 changes: 41 additions & 4 deletions controllers/keystoneapi_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,17 +233,19 @@ func (r *KeystoneAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request)

// fields to index to reconcile when change
const (
passwordSecretField = ".spec.secret"
caBundleSecretNameField = ".spec.tls.caBundleSecretName"
tlsAPIInternalField = ".spec.tls.api.internal.secretName"
tlsAPIPublicField = ".spec.tls.api.public.secretName"
passwordSecretField = ".spec.secret"
caBundleSecretNameField = ".spec.tls.caBundleSecretName"
tlsAPIInternalField = ".spec.tls.api.internal.secretName"
tlsAPIPublicField = ".spec.tls.api.public.secretName"
httpdCustomServiceConfigSecretField = ".spec.httpdCustomization.customServiceConfigSecret"
)

var allWatchFields = []string{
passwordSecretField,
caBundleSecretNameField,
tlsAPIInternalField,
tlsAPIPublicField,
httpdCustomServiceConfigSecretField,
}

// SetupWithManager -
Expand Down Expand Up @@ -298,6 +300,18 @@ func (r *KeystoneAPIReconciler) SetupWithManager(ctx context.Context, mgr ctrl.M
return err
}

// index httpdOverrideSecretField
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &keystonev1.KeystoneAPI{}, httpdCustomServiceConfigSecretField, func(rawObj client.Object) []string {
// Extract the secret name from the spec, if one is provided
cr := rawObj.(*keystonev1.KeystoneAPI)
if cr.Spec.HttpdCustomization.CustomServiceConfigSecret == nil {
return nil
}
return []string{*cr.Spec.HttpdCustomization.CustomServiceConfigSecret}
}); err != nil {
return err
}

memcachedFn := func(ctx context.Context, o client.Object) []reconcile.Request {
result := []reconcile.Request{}

Expand Down Expand Up @@ -1201,7 +1215,19 @@ func (r *KeystoneAPIReconciler) generateServiceConfigMaps(
"fernetMaxActiveKeys": instance.Spec.FernetMaxActiveKeys,
}

templateParameters["KeystoneEndpointPublic"], _ = instance.GetEndpoint(endpoint.EndpointPublic)
templateParameters["KeystoneEndpointInternal"], _ = instance.GetEndpoint(endpoint.EndpointInternal)

httpdOverrideSecret := &corev1.Secret{}
if instance.Spec.HttpdCustomization.CustomServiceConfigSecret != nil && *instance.Spec.HttpdCustomization.CustomServiceConfigSecret != "" {
httpdOverrideSecret, _, err = oko_secret.GetSecret(ctx, h, *instance.Spec.HttpdCustomization.CustomServiceConfigSecret, instance.Namespace)
if err != nil {
return err
}
}

// create httpd vhost template parameters
customTemplates := map[string]string{}
httpdVhostConfig := map[string]interface{}{}
for _, endpt := range []service.Endpoint{service.EndpointInternal, service.EndpointPublic} {
endptConfig := map[string]interface{}{}
Expand All @@ -1212,6 +1238,16 @@ func (r *KeystoneAPIReconciler) generateServiceConfigMaps(
endptConfig["SSLCertificateFile"] = fmt.Sprintf("/etc/pki/tls/certs/%s.crt", endpt.String())
endptConfig["SSLCertificateKeyFile"] = fmt.Sprintf("/etc/pki/tls/private/%s.key", endpt.String())
}

endptConfig["Override"] = false
if len(httpdOverrideSecret.Data) > 0 {
endptConfig["Override"] = true
for key, data := range httpdOverrideSecret.Data {
if len(data) > 0 {
customTemplates["httpd_custom_"+endpt.String()+"_"+key] = string(data)
}
}
}
httpdVhostConfig[endpt.String()] = endptConfig
}
templateParameters["VHosts"] = httpdVhostConfig
Expand All @@ -1231,6 +1267,7 @@ func (r *KeystoneAPIReconciler) generateServiceConfigMaps(
Namespace: instance.Namespace,
Type: util.TemplateTypeConfig,
InstanceType: instance.Kind,
RawTemplate: customTemplates,
CustomData: customData,
ConfigOptions: templateParameters,
Labels: cmLabels,
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,5 @@ replace github.com/openstack-k8s-operators/keystone-operator/api => ./api
// mschuppert: map to latest commit from release-4.16 tag
// must consistent within modules and service operators
replace github.com/openshift/api => github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 //allow-merging

replace github.com/openstack-k8s-operators/lib-common/modules/common => github.com/stuggi/lib-common/modules/common v0.0.0-20250110132704-f4bf5c3b0892
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094 h1:J1wuGhVxpsHykZBa6
github.com/openshift/api v0.0.0-20240830023148-b7d0481c9094/go.mod h1:CxgbWAlvu2iQB0UmKTtRu1YfepRg1/vJ64n2DlIEVz4=
github.com/openstack-k8s-operators/infra-operator/apis v0.5.1-0.20241217075239-1fc4566cc5ab h1:Pm9zQyhrs/zGAk9jvyt0hSBP28aHsFdWyI99M/lvFxU=
github.com/openstack-k8s-operators/infra-operator/apis v0.5.1-0.20241217075239-1fc4566cc5ab/go.mod h1:SSYBbFbgQbOwyY2cQNet7fSdQHHPb2rLo6GXE97Awp8=
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20241216113837-d172b3ac0f4e h1:hf4kVQBkyG79WcHBxdQ25QrDBbGFdarebS1Tc0Xclq4=
github.com/openstack-k8s-operators/lib-common/modules/common v0.5.1-0.20241216113837-d172b3ac0f4e/go.mod h1:YpNTuJhDWhbXM50O3qBkhO7M+OOyRmWkNVmJ4y3cyFs=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20241216113837-d172b3ac0f4e h1:HFo4OqPY0x4ZQeaWI2YGonTXAGTQFt+rOEJlfZVhS7s=
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.5.1-0.20241216113837-d172b3ac0f4e/go.mod h1:IASoGvp5QM/tBJUd/8i8uIjj4DBnI+64Ydh4r7pmnvA=
github.com/openstack-k8s-operators/lib-common/modules/test v0.5.1-0.20241216113837-d172b3ac0f4e h1:/iWDp3j+ET3gE5IjKHtdZaPd4SQyLHB/4L5jB16cV3I=
Expand All @@ -108,6 +106,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stuggi/lib-common/modules/common v0.0.0-20250110132704-f4bf5c3b0892 h1:nODvJKaxN/T3Lzo/peopLL/UL5fT0aZdQ0XHT/Ql6u4=
github.com/stuggi/lib-common/modules/common v0.0.0-20250110132704-f4bf5c3b0892/go.mod h1:YpNTuJhDWhbXM50O3qBkhO7M+OOyRmWkNVmJ4y3cyFs=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down
5 changes: 5 additions & 0 deletions templates/keystoneapi/config/httpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,10 @@ CustomLog /dev/stdout proxy env=forwarded
WSGIProcessGroup {{ $endpt }}
WSGIScriptAlias / "/usr/bin/keystone-wsgi-public"
WSGIPassAuthorization On

{{- if $vhost.Override }}
Include conf/httpd_override_{{ $endpt }}_*
{{- end }}

</VirtualHost>
{{ end }}
11 changes: 9 additions & 2 deletions templates/keystoneapi/config/keystone-api-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@
{
"source": "/var/lib/config-data/default/httpd.conf",
"dest": "/etc/httpd/conf/httpd.conf",
"owner": "root",
"owner": "apache",
"perm": "0644"
},
{
"source": "/var/lib/config-data/default/ssl.conf",
"dest": "/etc/httpd/conf.d/ssl.conf",
"owner": "root",
"owner": "apache",
"perm": "0644"
},
{
Expand Down Expand Up @@ -58,6 +58,13 @@
"dest": "/etc/my.cnf",
"owner": "keystone",
"perm": "0644"
},
{
"source": "/var/lib/config-data/default/httpd_override_*",
"dest": "/etc/httpd/conf/",
"owner": "apache",
"perm": "0444",
"optional": true
}
]
}
66 changes: 66 additions & 0 deletions tests/functional/keystoneapi_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,72 @@ var _ = Describe("Keystone controller", func() {
})
})

When("A KeystoneAPI is created with HttpdCustomization.OverrideSecret", func() {
BeforeEach(func() {
customServiceConfigSecretName := types.NamespacedName{Name: "foo", Namespace: namespace}
customConfig := []byte(`OIDCResponseType "id_token"
OIDCMemCacheServers "{{ .memcachedServers }}"
OIDCRedirectURI "{{ .KeystoneEndpointPublic }}/v3/auth/OS-FEDERATION/websso/openid"`)
th.CreateSecret(
customServiceConfigSecretName,
map[string][]byte{
"bar.conf": customConfig,
},
)

spec := GetDefaultKeystoneAPISpec()
spec["httpdCustomization"] = map[string]interface{}{
"customServiceConfigSecret": customServiceConfigSecretName.Name,
}

DeferCleanup(
k8sClient.Delete, ctx, CreateKeystoneMessageBusSecret(namespace, "rabbitmq-secret"))
keystone := CreateKeystoneAPI(keystoneAPIName, spec)
DeferCleanup(th.DeleteInstance, keystone)
DeferCleanup(
k8sClient.Delete, ctx, CreateKeystoneAPISecret(namespace, SecretName))
DeferCleanup(infra.DeleteMemcached, infra.CreateMemcached(namespace, "memcached", memcachedSpec))
DeferCleanup(
mariadb.DeleteDBService,
mariadb.CreateDBService(
namespace,
GetKeystoneAPI(keystoneAPIName).Spec.DatabaseInstance,
corev1.ServiceSpec{
Ports: []corev1.ServicePort{{Port: 3306}},
},
),
)
mariadb.SimulateMariaDBAccountCompleted(keystoneAccountName)
mariadb.SimulateMariaDBDatabaseCompleted(keystoneDatabaseName)
infra.SimulateTransportURLReady(types.NamespacedName{
Name: fmt.Sprintf("%s-keystone-transport", keystoneAPIName.Name),
Namespace: namespace,
})
infra.SimulateMemcachedReady(types.NamespacedName{
Name: "memcached",
Namespace: namespace,
})
th.SimulateJobSuccess(dbSyncJobName)
th.SimulateJobSuccess(bootstrapJobName)
th.SimulateDeploymentReplicaReady(deploymentName)
})

It("it renders the overrideTemplate and adds it to the keystone-config-data secret", func() {
scrt := th.GetSecret(keystoneAPIConfigDataName)
Expect(scrt).ShouldNot(BeNil())
for _, cfg := range []string{"httpd_custom_internal_bar.conf", "httpd_custom_public_bar.conf"} {
Expect(scrt.Data).Should(HaveKey(cfg))
configData := string(scrt.Data[cfg])
Expect(configData).Should(ContainSubstring("OIDCResponseType \"id_token\""))
Expect(configData).Should(ContainSubstring(
fmt.Sprintf("OIDCMemCacheServers \"memcached-0.memcached.%s.svc:11211,memcached-1.memcached.%s.svc:11211,memcached-2.memcached.%s.svc:11211\"",
namespace, namespace, namespace)))
Expect(configData).Should(ContainSubstring(
fmt.Sprintf("OIDCRedirectURI \"http://keystone-public.%s.svc:5000/v3/auth/OS-FEDERATION/websso/openid\"", namespace)))
}
})
})

// Run MariaDBAccount suite tests. these are pre-packaged ginkgo tests
// that exercise standard account create / update patterns that should be
// common to all controllers that ensure MariaDBAccount CRs.
Expand Down

0 comments on commit 3974d63

Please sign in to comment.