Skip to content
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
8 changes: 8 additions & 0 deletions api/bases/swift.openstack.org_swiftproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ spec:
60 seconds
minimum: 1
type: integer
auth:
description: Auth - Parameters related to authentication
properties:
applicationCredentialSecret:
description: ApplicationCredentialSecret - Secret containing Application
Credential ID and Secret
type: string
type: object
ceilometerEnabled:
default: false
description: Enables ceilometer in the swift proxy and creates required
Expand Down
8 changes: 8 additions & 0 deletions api/bases/swift.openstack.org_swifts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ spec:
to 60 seconds
minimum: 1
type: integer
auth:
description: Auth - Parameters related to authentication
properties:
applicationCredentialSecret:
description: ApplicationCredentialSecret - Secret containing
Application Credential ID and Secret
type: string
type: object
ceilometerEnabled:
default: false
description: Enables ceilometer in the swift proxy and creates
Expand Down
2 changes: 1 addition & 1 deletion api/v1beta1/swift_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ limitations under the License.
package v1beta1

import (
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
"github.com/openstack-k8s-operators/lib-common/modules/common/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
)

const (
Expand Down
17 changes: 15 additions & 2 deletions api/v1beta1/swiftproxy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ limitations under the License.
package v1beta1

import (
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
"github.com/openstack-k8s-operators/lib-common/modules/common/service"
"github.com/openstack-k8s-operators/lib-common/modules/common/tls"
"k8s.io/apimachinery/pkg/util/validation/field"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand Down Expand Up @@ -90,6 +90,11 @@ type SwiftProxySpecCore struct {
// TLS - Parameters related to the TLS
TLS tls.API `json:"tls,omitempty"`

// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec
// Auth - Parameters related to authentication
Auth AuthSpec `json:"auth,omitempty"`

// DefaultConfigOverwrite - can be used to add additionalfiles. Those get
// added to the service config dir in /etc/<servicename>-conf.d
DefaultConfigOverwrite map[string]string `json:"defaultConfigOverwrite,omitempty"`
Expand Down Expand Up @@ -132,6 +137,14 @@ type ProxyOverrideSpec struct {
Service map[service.Endpoint]service.RoutedOverrideSpec `json:"service,omitempty"`
}

// AuthSpec defines authentication parameters
type AuthSpec struct {
// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec
// ApplicationCredentialSecret - Secret containing Application Credential ID and Secret
ApplicationCredentialSecret string `json:"applicationCredentialSecret,omitempty"`
}

// SwiftProxyStatus defines the observed state of SwiftProxy
type SwiftProxyStatus struct {
// ReadyCount of SwiftProxy instances
Expand Down
16 changes: 16 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.

8 changes: 8 additions & 0 deletions config/crd/bases/swift.openstack.org_swiftproxies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ spec:
60 seconds
minimum: 1
type: integer
auth:
description: Auth - Parameters related to authentication
properties:
applicationCredentialSecret:
description: ApplicationCredentialSecret - Secret containing Application
Credential ID and Secret
type: string
type: object
ceilometerEnabled:
default: false
description: Enables ceilometer in the swift proxy and creates required
Expand Down
8 changes: 8 additions & 0 deletions config/crd/bases/swift.openstack.org_swifts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ spec:
to 60 seconds
minimum: 1
type: integer
auth:
description: Auth - Parameters related to authentication
properties:
applicationCredentialSecret:
description: ApplicationCredentialSecret - Secret containing
Application Credential ID and Secret
type: string
type: object
ceilometerEnabled:
default: false
description: Enables ceilometer in the swift proxy and creates
Expand Down
8 changes: 5 additions & 3 deletions internal/controller/swift_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ import (
"fmt"
"time"

topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
"github.com/openstack-k8s-operators/lib-common/modules/common/env"
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
"github.com/openstack-k8s-operators/lib-common/modules/common/secret"
"k8s.io/apimachinery/pkg/types"

topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
"github.com/openstack-k8s-operators/lib-common/modules/common/env"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/log"
Expand All @@ -42,6 +42,7 @@ const (
tlsAPIInternalField = ".spec.tls.api.internal.secretName"
tlsAPIPublicField = ".spec.tls.api.public.secretName"
topologyField = ".spec.topologyRef.Name"
authAppCredSecretField = ".spec.auth.applicationCredentialSecret" //nolint:gosec // G101:
)

var (
Expand All @@ -55,6 +56,7 @@ var (
tlsAPIInternalField,
tlsAPIPublicField,
topologyField,
authAppCredSecretField,
}
)

Expand Down
1 change: 1 addition & 0 deletions internal/controller/swift_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ func (r *SwiftReconciler) proxyCreateOrUpdate(ctx context.Context, instance *swi
NetworkAttachments: instance.Spec.SwiftProxy.NetworkAttachments,
MemcachedInstance: instance.Spec.MemcachedInstance,
TLS: instance.Spec.SwiftProxy.TLS,
Auth: instance.Spec.SwiftProxy.Auth,
DefaultConfigOverwrite: instance.Spec.SwiftProxy.DefaultConfigOverwrite,
EncryptionEnabled: instance.Spec.SwiftProxy.EncryptionEnabled,
RabbitMqClusterName: instance.Spec.SwiftProxy.RabbitMqClusterName,
Expand Down
53 changes: 53 additions & 0 deletions internal/controller/swiftproxy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,44 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
return ctrl.Result{}, err
}

// Get Application Credential data if available
useAC := false
acID := ""
acSecret := ""
// Try to get Application Credential from the secret specified in the CR
if instance.Spec.Auth.ApplicationCredentialSecret != "" {
acSecretObj, _, err := secret.GetSecret(ctx, helper, instance.Spec.Auth.ApplicationCredentialSecret, instance.Namespace)
if err != nil {
if apierrors.IsNotFound(err) {
Log.Info("ApplicationCredential secret not found, waiting", "secret", instance.Spec.Auth.ApplicationCredentialSecret)
instance.Status.Conditions.Set(condition.FalseCondition(
condition.InputReadyCondition,
condition.RequestedReason,
condition.SeverityInfo,
condition.InputReadyWaitingMessage))
return ctrl.Result{RequeueAfter: time.Second * 10}, nil
}
Log.Error(err, "Failed to get ApplicationCredential secret", "secret", instance.Spec.Auth.ApplicationCredentialSecret)
return ctrl.Result{}, err
}
acIDData, okID := acSecretObj.Data[keystonev1.ACIDSecretKey]
acSecretData, okSecret := acSecretObj.Data[keystonev1.ACSecretSecretKey]
if !okID || len(acIDData) == 0 || !okSecret || len(acSecretData) == 0 {
Log.Info("ApplicationCredential secret missing required keys", "secret", instance.Spec.Auth.ApplicationCredentialSecret)
instance.Status.Conditions.Set(condition.FalseCondition(
condition.InputReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
"ApplicationCredential secret %s missing required keys (AC_ID, AC_SECRET)",
instance.Spec.Auth.ApplicationCredentialSecret))
return ctrl.Result{RequeueAfter: time.Second * 10}, nil
}
useAC = true
acID = string(acIDData)
acSecret = string(acSecretData)
Log.Info("Using ApplicationCredentials auth", "secret", instance.Spec.Auth.ApplicationCredentialSecret)
}

// Create a Secret populated with content from templates/
tpl := swiftproxy.SecretTemplates(
instance,
Expand All @@ -591,6 +629,9 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
os.GetRegion(),
transportURLString,
instance.Spec.APITimeout,
useAC,
acID,
acSecret,
)
err = secret.EnsureSecrets(ctx, helper, instance, tpl, &envVars)
if err != nil {
Expand Down Expand Up @@ -817,6 +858,18 @@ func (r *SwiftProxyReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma
return err
}

// index authAppCredSecretField
if err := mgr.GetFieldIndexer().IndexField(context.Background(), &swiftv1beta1.SwiftProxy{}, authAppCredSecretField, func(rawObj client.Object) []string {
// Extract the application credential secret name from the spec, if one is provided
cr := rawObj.(*swiftv1beta1.SwiftProxy)
if cr.Spec.Auth.ApplicationCredentialSecret == "" {
return nil
}
return []string{cr.Spec.Auth.ApplicationCredentialSecret}
}); err != nil {
return err
}

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

Expand Down
10 changes: 10 additions & 0 deletions internal/swiftproxy/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ func SecretTemplates(
keystoneRegion string,
transportURL string,
apiTimeout int,
useApplicationCredentials bool,
applicationCredentialID string,
applicationCredentialSecret string,
) []util.Template {
templateParameters := make(map[string]any)
templateParameters["ServiceUser"] = instance.Spec.ServiceUser
Expand All @@ -54,6 +57,13 @@ func SecretTemplates(
templateParameters["TransportURL"] = transportURL
templateParameters["APITimeout"] = apiTimeout

// Application Credential parameters
templateParameters["UseApplicationCredentials"] = useApplicationCredentials
if useApplicationCredentials {
templateParameters["ApplicationCredentialID"] = applicationCredentialID
templateParameters["ApplicationCredentialSecret"] = applicationCredentialSecret
}

// MTLS params
if mc.Status.MTLSCert != "" {
templateParameters["MemcachedAuthCert"] = fmt.Sprint(memcachedv1.CertMountPath())
Expand Down
18 changes: 15 additions & 3 deletions templates/swiftproxy/config/00-proxy-server.conf
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,18 @@ project_reader_roles = SwiftProjectReader
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
www_authenticate_uri = {{ .KeystonePublicURL }}
auth_url = {{ .KeystonePublicURL }}
{{ if .UseApplicationCredentials -}}
auth_type = v3applicationcredential
application_credential_id = {{ .ApplicationCredentialID }}
application_credential_secret = {{ .ApplicationCredentialSecret }}
{{- else -}}
auth_plugin=password
username = {{ .ServiceUser }}
password = {{ .ServicePassword }}
project_domain_id = default
user_domain_id = default
project_name = service
username = {{ .ServiceUser }}
password = {{ .ServicePassword }}
{{- end }}
{{ if (index . "KeystoneRegion") -}}
region_name = {{ .KeystoneRegion }}
{{ end -}}
Expand Down Expand Up @@ -121,9 +127,15 @@ use = egg:swift#encryption
[filter:ceilometer]
paste.filter_factory = ceilometermiddleware.swift:filter_factory
auth_url = {{ .KeystonePublicURL }}
{{ if .UseApplicationCredentials -}}
auth_type = v3applicationcredential
application_credential_id = {{ .ApplicationCredentialID }}
application_credential_secret = {{ .ApplicationCredentialSecret }}
{{- else -}}
password = {{ .ServicePassword }}
username = {{ .ServiceUser }}
project_name = service
{{- end }}
region_name = {{ .KeystoneRegion }}
url = {{ .TransportURL }}
project_name = service
nonblocking_notify = True