Skip to content

Commit

Permalink
operator: Add support for Swift TLS CA configuration (#11708)
Browse files Browse the repository at this point in the history
Co-authored-by: Cyril Tovena <[email protected]>
  • Loading branch information
btaani and cyriltovena authored Apr 19, 2024
1 parent 0cb470f commit c1415c5
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 23 deletions.
2 changes: 2 additions & 0 deletions operator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Main

- [11708](https://github.com/grafana/loki/pull/11708) **btaani**: Add support for Swift TLS CA configuration

## 0.6.0 (2024-03-19)

- [12228](https://github.com/grafana/loki/pull/12228) **xperimental**: Restructure LokiStack metrics
Expand Down
66 changes: 48 additions & 18 deletions operator/internal/manifests/storage/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,23 @@ var (
// based on the object storage type. Currently supported amendments:
// - All: Ensure object storage secret mounted and auth projected as env vars.
// - GCS: Ensure env var GOOGLE_APPLICATION_CREDENTIALS in container
// - S3: Ensure mounting custom CA configmap if any TLSConfig given
// - S3 & Swift: Ensure mounting custom CA configmap if any TLSConfig given
func ConfigureDeployment(d *appsv1.Deployment, opts Options) error {
switch opts.SharedStore {
case lokiv1.ObjectStorageSecretAlibabaCloud, lokiv1.ObjectStorageSecretAzure, lokiv1.ObjectStorageSecretGCS, lokiv1.ObjectStorageSecretSwift:
case lokiv1.ObjectStorageSecretAlibabaCloud, lokiv1.ObjectStorageSecretAzure, lokiv1.ObjectStorageSecretGCS:
return configureDeployment(d, opts)
case lokiv1.ObjectStorageSecretS3:
err := configureDeployment(d, opts)
if err != nil {
return err
}
return configureDeploymentCA(d, opts.TLS)
return configureDeploymentCA(d, opts.TLS, lokiv1.ObjectStorageSecretS3)
case lokiv1.ObjectStorageSecretSwift:
err := configureDeployment(d, opts)
if err != nil {
return err
}
return configureDeploymentCA(d, opts.TLS, lokiv1.ObjectStorageSecretSwift)
default:
return nil
}
Expand All @@ -49,16 +55,21 @@ func ConfigureDeployment(d *appsv1.Deployment, opts Options) error {
// based on the object storage type. Currently supported amendments:
// - All: Ensure object storage secret mounted and auth projected as env vars.
// - GCS: Ensure env var GOOGLE_APPLICATION_CREDENTIALS in container
// - S3: Ensure mounting custom CA configmap if any TLSConfig given
// - S3 & Swift: Ensure mounting custom CA configmap if any TLSConfig given
func ConfigureStatefulSet(d *appsv1.StatefulSet, opts Options) error {
switch opts.SharedStore {
case lokiv1.ObjectStorageSecretAlibabaCloud, lokiv1.ObjectStorageSecretAzure, lokiv1.ObjectStorageSecretGCS, lokiv1.ObjectStorageSecretSwift:
case lokiv1.ObjectStorageSecretAlibabaCloud, lokiv1.ObjectStorageSecretAzure, lokiv1.ObjectStorageSecretGCS:
return configureStatefulSet(d, opts)
case lokiv1.ObjectStorageSecretS3:
if err := configureStatefulSet(d, opts); err != nil {
return err
}
return configureStatefulSetCA(d, opts.TLS)
return configureStatefulSetCA(d, opts.TLS, lokiv1.ObjectStorageSecretS3)
case lokiv1.ObjectStorageSecretSwift:
if err := configureStatefulSet(d, opts); err != nil {
return err
}
return configureStatefulSetCA(d, opts.TLS, lokiv1.ObjectStorageSecretSwift)
default:
return nil
}
Expand All @@ -75,16 +86,22 @@ func configureDeployment(d *appsv1.Deployment, opts Options) error {
return nil
}

// ConfigureDeploymentCA merges a S3 CA ConfigMap volume into the deployment spec.
func configureDeploymentCA(d *appsv1.Deployment, tls *TLSConfig) error {
// ConfigureDeploymentCA merges a S3 or Swift CA ConfigMap volume into the deployment spec.
func configureDeploymentCA(d *appsv1.Deployment, tls *TLSConfig, secretType lokiv1.ObjectStorageSecretType) error {
if tls == nil {
return nil
}

p := ensureCAForS3(&d.Spec.Template.Spec, tls)
var p corev1.PodSpec
switch secretType {
case lokiv1.ObjectStorageSecretS3:
p = ensureCAForObjectStorage(&d.Spec.Template.Spec, tls, lokiv1.ObjectStorageSecretS3)
case lokiv1.ObjectStorageSecretSwift:
p = ensureCAForObjectStorage(&d.Spec.Template.Spec, tls, lokiv1.ObjectStorageSecretSwift)
}

if err := mergo.Merge(&d.Spec.Template.Spec, p, mergo.WithOverride); err != nil {
return kverrors.Wrap(err, "failed to merge s3 object storage ca options ")
return kverrors.Wrap(err, "failed to merge object storage ca options ")
}

return nil
Expand All @@ -101,16 +118,22 @@ func configureStatefulSet(s *appsv1.StatefulSet, opts Options) error {
return nil
}

// ConfigureStatefulSetCA merges a S3 CA ConfigMap volume into the statefulset spec.
func configureStatefulSetCA(s *appsv1.StatefulSet, tls *TLSConfig) error {
// ConfigureStatefulSetCA merges a S3 or Swift CA ConfigMap volume into the statefulset spec.
func configureStatefulSetCA(s *appsv1.StatefulSet, tls *TLSConfig, secretType lokiv1.ObjectStorageSecretType) error {
if tls == nil {
return nil
}
var p corev1.PodSpec

p := ensureCAForS3(&s.Spec.Template.Spec, tls)
switch secretType {
case lokiv1.ObjectStorageSecretS3:
p = ensureCAForObjectStorage(&s.Spec.Template.Spec, tls, lokiv1.ObjectStorageSecretS3)
case lokiv1.ObjectStorageSecretSwift:
p = ensureCAForObjectStorage(&s.Spec.Template.Spec, tls, lokiv1.ObjectStorageSecretSwift)
}

if err := mergo.Merge(&s.Spec.Template.Spec, p, mergo.WithOverride); err != nil {
return kverrors.Wrap(err, "failed to merge s3 object storage ca options ")
return kverrors.Wrap(err, "failed to merge object storage ca options ")
}

return nil
Expand Down Expand Up @@ -246,7 +269,7 @@ func serverSideEncryption(opts Options) []corev1.EnvVar {
}
}

func ensureCAForS3(p *corev1.PodSpec, tls *TLSConfig) corev1.PodSpec {
func ensureCAForObjectStorage(p *corev1.PodSpec, tls *TLSConfig, secretType lokiv1.ObjectStorageSecretType) corev1.PodSpec {
container := p.Containers[0].DeepCopy()
volumes := p.Volumes

Expand All @@ -267,9 +290,16 @@ func ensureCAForS3(p *corev1.PodSpec, tls *TLSConfig) corev1.PodSpec {
MountPath: caDirectory,
})

container.Args = append(container.Args,
fmt.Sprintf("-s3.http.ca-file=%s", path.Join(caDirectory, tls.Key)),
)
switch secretType {
case lokiv1.ObjectStorageSecretS3:
container.Args = append(container.Args,
fmt.Sprintf("-s3.http.ca-file=%s", path.Join(caDirectory, tls.Key)),
)
case lokiv1.ObjectStorageSecretSwift:
container.Args = append(container.Args,
fmt.Sprintf("-swift.http.ca-file=%s", path.Join(caDirectory, tls.Key)),
)
}

return corev1.PodSpec{
Containers: []corev1.Container{
Expand Down
202 changes: 197 additions & 5 deletions operator/internal/manifests/storage/configure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2505,6 +2505,102 @@ func TestConfigureDeploymentForStorageCA(t *testing.T) {
},
},
},
{
desc: "object storage Swift",
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretSwift,
TLS: &TLSConfig{
CA: "test",
Key: "service-ca.crt",
},
},
dpl: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "loki-querier",
},
},
},
},
},
},
want: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "loki-querier",
VolumeMounts: []corev1.VolumeMount{
{
Name: "test",
ReadOnly: false,
MountPath: "/etc/storage/secrets",
},
{
Name: "storage-tls",
ReadOnly: false,
MountPath: "/etc/storage/ca",
},
},
Args: []string{
"-swift.http.ca-file=/etc/storage/ca/service-ca.crt",
},
Env: []corev1.EnvVar{
{
Name: EnvSwiftUsername,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
Key: KeySwiftUsername,
},
},
},
{
Name: EnvSwiftPassword,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
Key: KeySwiftPassword,
},
},
},
},
},
},
Volumes: []corev1.Volume{
{
Name: "test",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: "test",
},
},
},
{
Name: "storage-tls",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
},
},
},
},
},
},
},
},
},
}

for _, tc := range tc {
Expand All @@ -2531,7 +2627,7 @@ func TestConfigureStatefulSetForStorageCA(t *testing.T) {
desc: "object storage other than S3",
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretSwift,
SharedStore: lokiv1.ObjectStorageSecretAzure,
TLS: &TLSConfig{
CA: "test",
},
Expand Down Expand Up @@ -2565,24 +2661,24 @@ func TestConfigureStatefulSetForStorageCA(t *testing.T) {
},
Env: []corev1.EnvVar{
{
Name: EnvSwiftUsername,
Name: EnvAzureStorageAccountName,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
Key: KeySwiftUsername,
Key: KeyAzureStorageAccountName,
},
},
},
{
Name: EnvSwiftPassword,
Name: EnvAzureStorageAccountKey,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
Key: KeySwiftPassword,
Key: KeyAzureStorageAccountKey,
},
},
},
Expand Down Expand Up @@ -2700,6 +2796,102 @@ func TestConfigureStatefulSetForStorageCA(t *testing.T) {
},
},
},
{
desc: "object storage Swift",
opts: Options{
SecretName: "test",
SharedStore: lokiv1.ObjectStorageSecretSwift,
TLS: &TLSConfig{
CA: "test",
Key: "service-ca.crt",
},
},
sts: &appsv1.StatefulSet{
Spec: appsv1.StatefulSetSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "loki-ingester",
},
},
},
},
},
},
want: &appsv1.StatefulSet{
Spec: appsv1.StatefulSetSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "loki-ingester",
VolumeMounts: []corev1.VolumeMount{
{
Name: "test",
ReadOnly: false,
MountPath: "/etc/storage/secrets",
},
{
Name: "storage-tls",
ReadOnly: false,
MountPath: "/etc/storage/ca",
},
},
Args: []string{
"-swift.http.ca-file=/etc/storage/ca/service-ca.crt",
},
Env: []corev1.EnvVar{
{
Name: EnvSwiftUsername,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
Key: KeySwiftUsername,
},
},
},
{
Name: EnvSwiftPassword,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
Key: KeySwiftPassword,
},
},
},
},
},
},
Volumes: []corev1.Volume{
{
Name: "test",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: "test",
},
},
},
{
Name: "storage-tls",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: "test",
},
},
},
},
},
},
},
},
},
},
}

for _, tc := range tc {
Expand Down

0 comments on commit c1415c5

Please sign in to comment.