Skip to content

Commit

Permalink
adds feature flag to enable creation of AG TLS certificate
Browse files Browse the repository at this point in the history
  • Loading branch information
aorcholski committed Feb 24, 2025
1 parent 726338a commit 8cf1d94
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 20 deletions.
7 changes: 6 additions & 1 deletion doc/api/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ const (
AnnotationFeatureAutomaticK8sApiMonitoringClusterName = AnnotationFeaturePrefix + "automatic-kubernetes-api-monitoring-cluster-name"
AnnotationFeatureK8sAppEnabled = AnnotationFeaturePrefix + "k8s-app-enabled"

AnnotationFeatureActiveGateAutomaticTLSCertificate = AnnotationFeaturePrefix + "automatic-tls-certificate"

AnnotationFeatureNoProxy = AnnotationFeaturePrefix + "no-proxy"

AnnotationFeatureOneAgnetIgnoreAgTlsCertificate = AnnotationFeaturePrefix + "oneagent-ignore-ag-tls-certificate"
AnnotationFeatureOneAgnetIgnoreTrustedCAs = AnnotationFeaturePrefix + "oneagent-ignore-trusted-cas"

// Deprecated: AnnotationFeatureOneAgentIgnoreProxy use AnnotationFeatureNoProxy instead.
AnnotationFeatureOneAgentIgnoreProxy = AnnotationFeaturePrefix + "oneagent-ignore-proxy"

Expand Down Expand Up @@ -74,7 +79,7 @@ const (

<a name="MountAttemptsToTimeout"></a>

## func [MountAttemptsToTimeout](<https://github.com/Dynatrace/dynatrace-operator/blob/main/pkg/api/v1beta3/dynakube/tmp/feature_flags.go#L261>)
## func [MountAttemptsToTimeout](<https://github.com/Dynatrace/dynatrace-operator/blob/main/pkg/api/v1beta3/dynakube/tmp/feature_flags.go#L271>)

```go
func MountAttemptsToTimeout(maxAttempts int) string
Expand Down
18 changes: 9 additions & 9 deletions doc/e2e/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative"
## Index

- [func AssessActiveGateContainer(builder *features.FeatureBuilder, dk *dynakube.DynaKube, trustedCAs []byte)](<#AssessActiveGateContainer>)
- [func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, trustedCAs []byte)](<#AssessOneAgentContainer>)
- [func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt []byte, trustedCAs []byte)](<#AssessSampleContainer>)
- [func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt func() []byte, trustedCAs []byte)](<#AssessOneAgentContainer>)
- [func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt func() []byte, trustedCAs []byte)](<#AssessSampleContainer>)
- [func AssessSampleInitContainers(builder *features.FeatureBuilder, sampleApp *sample.App)](<#AssessSampleInitContainers>)
- [func DefaultCloudNativeSpec() *oneagent.CloudNativeFullStackSpec](<#DefaultCloudNativeSpec>)

Expand All @@ -146,15 +146,15 @@ func AssessActiveGateContainer(builder *features.FeatureBuilder, dk *dynakube.Dy
## func [AssessOneAgentContainer](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/container.go#L66>)

```go
func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt []byte, trustedCAs []byte)
func AssessOneAgentContainer(builder *features.FeatureBuilder, agCrt func() []byte, trustedCAs []byte)
```

<a name="AssessSampleContainer"></a>

## func [AssessSampleContainer](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/container.go#L28>)

```go
func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt []byte, trustedCAs []byte)
func AssessSampleContainer(builder *features.FeatureBuilder, sampleApp *sample.App, agCrt func() []byte, trustedCAs []byte)
```

<a name="AssessSampleInitContainers"></a>
Expand Down Expand Up @@ -189,7 +189,7 @@ import "github.com/Dynatrace/dynatrace-operator/test/features/cloudnative/codemo

<a name="InstallFromImage"></a>

## func [InstallFromImage](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L67>)
## func [InstallFromImage](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L68>)

```go
func InstallFromImage(t *testing.T) features.Feature
Expand All @@ -199,7 +199,7 @@ Verification that the storage in the CSI driver directory does not increase when

<a name="WithProxy"></a>

## func [WithProxy](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L136>)
## func [WithProxy](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L137>)

```go
func WithProxy(t *testing.T, proxySpec *value.Source) features.Feature
Expand All @@ -215,23 +215,23 @@ Connectivity in the dynatrace namespace and sample application namespace is rest

<a name="WithProxyAndAGCert"></a>

## func [WithProxyAndAGCert](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L251>)
## func [WithProxyAndAGCert](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L275>)

```go
func WithProxyAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature
```

<a name="WithProxyCA"></a>

## func [WithProxyCA](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L190>)
## func [WithProxyCA](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L191>)

```go
func WithProxyCA(t *testing.T, proxySpec *value.Source) features.Feature
```

<a name="WithProxyCAAndAGCert"></a>

## func [WithProxyCAAndAGCert](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L316>)
## func [WithProxyCAAndAGCert](<https://github.com/Dynatrace/dynatrace-operator/blob/main/test/features/cloudnative/codemodules/codemodules.go#L340>)

```go
func WithProxyCAAndAGCert(t *testing.T, proxySpec *value.Source) features.Feature
Expand Down
4 changes: 3 additions & 1 deletion hack/doc/gen_e2e_features.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ done

# remove gomarkdoc headers and add custom one
output=$(echo "${output}" | sed s/"$gomarkdoc_header"//)
output="${script_header}\n${output}"
output="${script_header}
${output}"

# write output to file
mkdir -p $output_dir
echo "$output" > $output_dir/$output_file
echo "$output" > ${output_dir/$output_file}2

# fix linting issues
markdownlint -f $output_dir/$output_file
3 changes: 2 additions & 1 deletion hack/doc/gen_feature_flags.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ output=$(echo "${output}" | sed '$d')

# remove gomarkdoc headers and add custom one
output=$(echo "${output}" | sed s/"$gomarkdoc_header"//)
output="${script_header}\n${output}"
output="${script_header}
${output}"

# write output to file
mkdir -p $output_dir
Expand Down
21 changes: 17 additions & 4 deletions pkg/api/v1beta3/dynakube/activegate/props.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func (ag *Spec) SetTrustedCAs(name string) {
ag.trustedCAs = name
}

func (ag *Spec) SetAutomaticTLSCertificate(enabled bool) {
ag.automaticTLSCertificateEnabled = enabled
}

func (ag *Spec) SetExtensionsDependency(isEnabled bool) {
ag.enabledDependencies.extensions = isEnabled
}
Expand Down Expand Up @@ -97,26 +101,35 @@ func (ag *Spec) IsMetricsIngestEnabled() bool {
return ag.IsMode(MetricsIngestCapability.DisplayName)
}

func (ag *Spec) IsAutomaticTlsSecretEnabled() bool {
return ag.TlsSecretName == "" && ag.trustedCAs != "" && ag.automaticTLSCertificateEnabled
}

func (ag *Spec) HasCaCert() bool {
return ag.IsEnabled() && (ag.TlsSecretName != "" || ag.TlsSecretName == "" && ag.trustedCAs != "")
return ag.IsEnabled() && (ag.TlsSecretName != "" || ag.IsAutomaticTlsSecretEnabled())
}

// ActivegateTenantSecret returns the name of the secret containing tenant UUID, token and communication endpoints for ActiveGate.
// GetTenantSecretName returns the name of the secret containing tenant UUID, token and communication endpoints for ActiveGate.
func (ag *Spec) GetTenantSecretName() string {
return ag.name + TenantSecretSuffix
}

// ActiveGateAuthTokenSecret returns the name of the secret containing the ActiveGateAuthToken, which is mounted to the AGs.
// GetAuthTokenSecretName returns the name of the secret containing the ActiveGateAuthToken, which is mounted to the AGs.
func (ag *Spec) GetAuthTokenSecretName() string {
return ag.name + AuthTokenSecretSuffix
}

// GetTlsSecretName returns the name of the AG TLS secret.
func (ag *Spec) GetTlsSecretName() string {
if ag.TlsSecretName != "" {
return ag.TlsSecretName
}

return ag.name + TlsSecretSuffix
if ag.IsAutomaticTlsSecretEnabled() {
return ag.name + TlsSecretSuffix
}

return ""
}

func (ag *Spec) GetConnectionInfoConfigMapName() string {
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/v1beta3/dynakube/activegate/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ type Spec struct {

enabledDependencies dependencies

automaticTLSCertificateEnabled bool

// UseEphemeralVolume
UseEphemeralVolume bool `json:"useEphemeralVolume,omitempty"`
}
Expand Down
1 change: 1 addition & 0 deletions pkg/api/v1beta3/dynakube/activegate_props.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ func (dk *DynaKube) ActiveGate() *activegate.ActiveGate {
dk.Spec.ActiveGate.SetApiUrl(dk.ApiUrl())
dk.Spec.ActiveGate.SetName(dk.Name)
dk.Spec.ActiveGate.SetTrustedCAs(dk.Spec.TrustedCAs)
dk.Spec.ActiveGate.SetAutomaticTLSCertificate(dk.FeatureActiveGateAutomaticTLSCertificate())
dk.Spec.ActiveGate.SetExtensionsDependency(dk.IsExtensionsEnabled())
dk.Spec.ActiveGate.SetOTLPingestDependency(dk.IsOTLPingestEnabled())

Expand Down
9 changes: 9 additions & 0 deletions pkg/api/v1beta3/dynakube/feature_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const (
AnnotationFeatureAutomaticK8sApiMonitoringClusterName = AnnotationFeaturePrefix + "automatic-kubernetes-api-monitoring-cluster-name"
AnnotationFeatureK8sAppEnabled = AnnotationFeaturePrefix + "k8s-app-enabled"

AnnotationFeatureActiveGateAutomaticTLSCertificate = AnnotationFeaturePrefix + "automatic-tls-certificate"

// dtClient.

AnnotationFeatureNoProxy = AnnotationFeaturePrefix + "no-proxy"
Expand Down Expand Up @@ -132,6 +134,11 @@ func (dk *DynaKube) FeatureNoProxy() string {
return dk.getFeatureFlagRaw(AnnotationFeatureNoProxy)
}

// FeatureActiveGateAutomaticTLSCertificate is a feature flag to enable automatic creation of AG TLS certificate if TrustedCAs are used.
func (dk *DynaKube) FeatureActiveGateAutomaticTLSCertificate() bool {
return dk.getFeatureFlagRaw(AnnotationFeatureActiveGateAutomaticTLSCertificate) == truePhrase
}

// FeatureOneAgentMaxUnavailable is a feature flag to configure maxUnavailable on the OneAgent DaemonSets rolling upgrades.
func (dk *DynaKube) FeatureOneAgentMaxUnavailable() int {
return dk.getFeatureFlagInt(AnnotationFeatureOneAgentMaxUnavailable, 1)
Expand Down Expand Up @@ -299,10 +306,12 @@ func (dk *DynaKube) FeatureEnforcementMode() bool {
return dk.getFeatureFlagRaw(AnnotationFeatureEnforcementMode) != falsePhrase
}

// FeatureOneAgentIgnoreActiveGateTlsCertificate is a feature flag to skip mounting AG TLS certificate to OneAgent POD.
func (dk *DynaKube) FeatureOneAgentIgnoreActiveGateTlsCertificate() bool {
return dk.getFeatureFlagRaw(AnnotationFeatureOneAgnetIgnoreAgTlsCertificate) == truePhrase
}

// FeatureOneAgentIgnoreTrustedCAs is a feature flag to skip mounting TrustedCAs certificates to OneAgent POD.
func (dk *DynaKube) FeatureOneAgentIgnoreTrustedCAs() bool {
return dk.getFeatureFlagRaw(AnnotationFeatureOneAgnetIgnoreTrustedCAs) == truePhrase
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func NewReconciler(client client.Client, apiReader client.Reader, dk *dynakube.D
}

func (r *Reconciler) Reconcile(ctx context.Context) error {
if r.dk.ActiveGate().IsEnabled() && r.dk.ActiveGate().TlsSecretName == "" && r.dk.Spec.TrustedCAs != "" {
if r.dk.ActiveGate().IsEnabled() && r.dk.ActiveGate().IsAutomaticTlsSecretEnabled() {
return r.reconcileSelfSignedTLSSecret(ctx)
}

Expand Down
49 changes: 47 additions & 2 deletions pkg/controllers/dynakube/extension/eec/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,7 @@ func TestActiveGateVolumes(t *testing.T) {
},
}

t.Run("ActiveGate tls certificate is mounted to EEC", func(t *testing.T) {
t.Run("volumes with custom ActiveGate tls certificate", func(t *testing.T) {
dk := getTestDynakube()
dk.Spec.ActiveGate.TlsSecretName = tlsSecretName
statefulSet := getStatefulset(t, dk)
Expand All @@ -983,7 +983,8 @@ func TestActiveGateVolumes(t *testing.T) {
require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount)
require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume)
})
t.Run("ActiveGate tls certificate is not mounted to EEC", func(t *testing.T) {

t.Run("volumes without custom ActiveGate tls certificate", func(t *testing.T) {
dk := getTestDynakube()
statefulSet := getStatefulset(t, dk)

Expand All @@ -994,4 +995,48 @@ func TestActiveGateVolumes(t *testing.T) {
require.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount)
require.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume)
})

t.Run("volumes with TrustedCAs certificates", func(t *testing.T) {
dk := getTestDynakube()
dk.Spec.TrustedCAs = "custom-tls"
statefulSet := getStatefulset(t, dk)

require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers)
require.NotEmpty(t, statefulSet.Spec.Template.Spec.Volumes)

require.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, expectedEnvVar)
require.NotContains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount)
require.NotContains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume)
})

t.Run("volumes with automatically created ActiveGate tls certificate", func(t *testing.T) {
dk := getTestDynakube()
dk.Annotations[dynakube.AnnotationFeatureActiveGateAutomaticTLSCertificate] = "true"
dk.Spec.TrustedCAs = "custom-tls"

expectedVolume := corev1.Volume{
Name: activeGateTrustedCertVolumeName,
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
DefaultMode: &defaultMode,
SecretName: dk.ActiveGate().GetTlsSecretName(),
Items: []corev1.KeyToPath{
{
Key: activeGateTrustedCertSecretKeyPath,
Path: activeGateTrustedCertSecretKeyPath,
},
},
},
},
}

statefulSet := getStatefulset(t, dk)

require.NotEmpty(t, statefulSet.Spec.Template.Spec.Containers)
require.NotEmpty(t, statefulSet.Spec.Template.Spec.Volumes)

require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].Env, expectedEnvVar)
require.Contains(t, statefulSet.Spec.Template.Spec.Containers[0].VolumeMounts, expectedVolumeMount)
require.Contains(t, statefulSet.Spec.Template.Spec.Volumes, expectedVolume)
})
}
Loading

0 comments on commit 8cf1d94

Please sign in to comment.