Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(operator): Add support for Swift TLS CA configuration #11708

Merged
merged 5 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions operator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Main

- [11708](https://github.com/grafana/loki/pull/11708) **btaani**: Add support for Swift TLS CA configuration
- [11671](https://github.com/grafana/loki/pull/11671) **JoaoBraveCoding**: Update mixins to fix structured metadata dashboards
- [11624](https://github.com/grafana/loki/pull/11624) **xperimental**: React to changes in ConfigMap used for storage CA
- [11481](https://github.com/grafana/loki/pull/11481) **JoaoBraveCoding**: Adds AWS STS support
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 @@ -17,17 +17,23 @@ import (
// 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 @@ -37,16 +43,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 @@ -64,16 +75,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 @@ -91,16 +108,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 @@ -203,7 +226,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 @@ -224,9 +247,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 @@ -1305,6 +1305,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 @@ -1331,7 +1427,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 @@ -1365,24 +1461,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 @@ -1500,6 +1596,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
Loading