Skip to content

enable SSL for the SDK pod #285

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

Merged
merged 49 commits into from
Jun 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
18d5436
initial TLS attempt
laverya Jun 2, 2025
061f307
remove broken 'make build-ttl.sh' command
laverya Jun 6, 2025
a4b2dbe
Update chart/values.yaml
laverya Jun 6, 2025
a506ba3
automatically set http/https status probe
laverya Jun 6, 2025
0d8e7f3
undo makefile change
laverya Jun 6, 2025
315c3a6
reinclude build-ttl.sh
laverya Jun 6, 2025
9e8d950
print image/chart locations in validate
laverya Jun 6, 2025
0c88660
new dagger command
laverya Jun 6, 2025
40cd6e8
f
laverya Jun 6, 2025
88c18ed
exit logging
laverya Jun 6, 2025
0efb1b9
more validation logging
laverya Jun 6, 2025
801f980
undo test chart related changes
laverya Jun 6, 2025
2d66114
wait 15 minutes
laverya Jun 6, 2025
be8f9a7
remove redundant logs
laverya Jun 6, 2025
b0732e2
add TLS testing
laverya Jun 6, 2025
97cde54
Merge remote-tracking branch 'origin/main' into laverya/sc-123955/ena…
laverya Jun 6, 2025
540d510
login to registry
laverya Jun 6, 2025
fa02e5a
add success log
laverya Jun 6, 2025
789e092
remove unneeded param from test-chart call
laverya Jun 6, 2025
79aab5e
fix the build ttl.sh call by making it call dagger instead
laverya Jun 6, 2025
7cade08
push wrapped chart in ttl.sh build, print destination
laverya Jun 6, 2025
5cf89b7
set the right helm value?
laverya Jun 6, 2025
cdfe05c
ensure that the SDK pod is actually serving TLS traffic after update
laverya Jun 6, 2025
7314277
yaml...
laverya Jun 6, 2025
847b7ec
fix deployment yaml
laverya Jun 6, 2025
12dd2ab
apply why?
laverya Jun 6, 2025
37daba1
logs?
laverya Jun 6, 2025
5449a86
bad deployment yaml test
laverya Jun 6, 2025
2eba412
stderr?
laverya Jun 6, 2025
ccf04d8
yaml formatting and logging
laverya Jun 6, 2025
07e1cd5
print deployment description after timeout
laverya Jun 6, 2025
7a6e6b3
check if replicated deployment is using https health check
laverya Jun 6, 2025
23f4e76
delete old pod before waiting for new one
laverya Jun 7, 2025
d82161f
dir?
laverya Jun 7, 2025
6e9dade
logs and secrets
laverya Jun 7, 2025
3371f3a
tls cert creation error checking
laverya Jun 7, 2025
134e0b7
pass certs properly?
laverya Jun 7, 2025
d884c7d
different type
laverya Jun 7, 2025
178c362
fix file path
laverya Jun 7, 2025
db11141
correct filepath fix?
laverya Jun 7, 2025
cf45f57
secret create command
laverya Jun 7, 2025
921765b
secret create logging
laverya Jun 7, 2025
8e08608
run ci again
laverya Jun 9, 2025
02303e6
check if a file not existing results in logs
laverya Jun 9, 2025
c927b2f
chmod +r cert files, only run openshift test
laverya Jun 9, 2025
20ccef9
F
laverya Jun 9, 2025
f38d860
final pod logging
laverya Jun 9, 2025
0ce091c
enable parallel tests again
laverya Jun 9, 2025
98c8d46
remove redundant pod deletion
laverya Jun 9, 2025
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
5 changes: 1 addition & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ vet:

.PHONY: build-ttl.sh
build-ttl.sh:
docker buildx build . -t ttl.sh/${USER}/replicated-sdk:24h -f deploy/Dockerfile --load
docker push ttl.sh/${USER}/replicated-sdk:24h

make -C chart build-ttl.sh
dagger call test-chart --progress=plain
Comment on lines -62 to +61
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the files this used to use were deleted with the move to dagger


.PHONY: mock
mock:
Expand Down
7 changes: 6 additions & 1 deletion chart/templates/replicated-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,12 @@ spec:
resources: {{- toYaml .Values.resources | nindent 10 }}
{{- end }}
{{- if .Values.readinessProbe }}
readinessProbe: {{- toYaml .Values.readinessProbe | nindent 10 }}
readinessProbe:
{{- $readinessProbe := .Values.readinessProbe | deepCopy }}
{{- if and .Values.tlsCertSecretName $readinessProbe.httpGet }}
{{- $_ := set $readinessProbe.httpGet "scheme" "HTTPS" }}
{{- end }}
{{- toYaml $readinessProbe | nindent 10 }}
{{- end }}
{{- if .Values.restartPolicy }}
restartPolicy: {{ .Values.restartPolicy }}
Expand Down
1 change: 1 addition & 0 deletions chart/templates/replicated-secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ stringData:
{{- end }}
replicatedID: {{ .Values.replicatedID | default "" | quote }}
appID: {{ .Values.appID | default "" | quote }}
tlsCertSecretName: {{ .Values.tlsCertSecretName | default "" | quote }}
{{- if (.Values.integration).licenseID }}
integration-license-id: {{ .Values.integration.licenseID }}
{{- end }}
Expand Down
7 changes: 6 additions & 1 deletion chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,13 @@ containerSecurityContext:

# Readiness probe configuration
# Determines when the container is ready to serve traffic
# Note: The scheme will automatically be set to HTTPS if tlsCertSecretName is provided
# Ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
readinessProbe:
httpGet: # Uses HTTP GET request to check health
path: /healthz # Endpoint to query
port: 3000 # Port to use
scheme: HTTP # Protocol (HTTP or HTTPS)
scheme: HTTP # Protocol (HTTP or HTTPS) - automatically set to HTTPS when TLS is enabled
failureThreshold: 3 # Number of failures before marking unready
initialDelaySeconds: 10 # Delay before first check
periodSeconds: 10 # How often to check
Expand Down Expand Up @@ -273,3 +274,7 @@ replicatedAppEndpoint: ""
# If not specified, the default domain "replicated.app" will be used
# Should not include the protocol, just the domain name
replicatedAppDomain: ""

# TLS Certificate Secret Name - the name of the secret containing a TLS certificate and key
# If not specified, TLS will not be enabled
tlsCertSecretName: ""
1 change: 1 addition & 0 deletions cmd/replicated/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func APICmd() *cobra.Command {
StatusInformers: replicatedConfig.StatusInformers,
ReplicatedID: replicatedConfig.ReplicatedID,
AppID: replicatedConfig.AppID,
TlsCertSecretName: replicatedConfig.TlsCertSecretName,
Namespace: namespace,
}
apiserver.Start(params)
Expand Down
177 changes: 171 additions & 6 deletions dagger/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func e2e(

out, err := ctr.Stdout(ctx)
if err != nil {
return err
return fmt.Errorf("failed to create cluster: %w", err)
}

type ReplicatedCluster struct {
Expand All @@ -35,7 +35,7 @@ func e2e(
}
replicatedCluster := ReplicatedCluster{}
if err := json.Unmarshal([]byte(out), &replicatedCluster); err != nil {
return err
return fmt.Errorf("failed to unmarshal cluster: %w", err)
}

// get the kubeconfig
Expand All @@ -45,7 +45,7 @@ func e2e(

kubeconfig, err := ctr.Stdout(ctx)
if err != nil {
return err
return fmt.Errorf("failed to get kubeconfig: %w", err)
}

kubeconfigSource := source.WithNewFile("/kubeconfig", kubeconfig)
Expand All @@ -57,7 +57,7 @@ func e2e(

out, err = ctr.Stdout(ctx)
if err != nil {
return err
return fmt.Errorf("failed to install chart: %w", err)
}

fmt.Println(out)
Expand All @@ -76,6 +76,7 @@ func e2e(

out, err = ctr.Stdout(ctx)
if err != nil {
fmt.Printf("failed to wait for deployment to be ready: %v\n", err)
// return err
}

Expand All @@ -91,7 +92,7 @@ func e2e(

out, err = ctr.Stdout(ctx)
if err != nil {
return err
return fmt.Errorf("failed to get namespaces: %w", err)
}

fmt.Println(out)
Expand All @@ -106,10 +107,174 @@ func e2e(

out, err = ctr.Stdout(ctx)
if err != nil {
return err
return fmt.Errorf("failed to get pods: %w", err)
}

fmt.Println(out)

// create a tls cert and key
certDir := dag.Container().From("alpine/openssl:latest").
WithWorkdir("/certs").
WithExec([]string{"openssl", "req", "-x509", "-newkey", "rsa:4096", "-keyout", "/certs/test-key.key", "-out", "/certs/test-cert.crt", "-days", "365", "-nodes", "-subj", "/CN=test.com"}).
WithExec([]string{"chmod", "+r", "/certs/test-cert.crt"}).
WithExec([]string{"chmod", "+r", "/certs/test-key.key"}).
Directory("/certs")

// create a TLS secret within the namespace
ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithFile("/certs/test-cert.crt", certDir.File("/test-cert.crt")).
WithFile("/certs/test-key.key", certDir.File("/test-key.key")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec(
[]string{
"kubectl", "create", "secret", "tls", "test-tls", "--cert=/certs/test-cert.crt", "--key=/certs/test-key.key",
})
out, err = ctr.Stdout(ctx)
if err != nil {
stderr, _ := ctr.Stderr(ctx)
return fmt.Errorf("failed to create tls secret: %w\n\nStderr: %s\n\nStdout: %s", err, stderr, out)
}
fmt.Println(out)

// update the chart to set TLS to true
ctr = dag.Container().From("alpine/helm:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithExec([]string{"helm", "registry", "login", "registry.replicated.com", "--username", "[email protected]", "--password", licenseID}).
WithExec([]string{"helm", "upgrade", "test-chart", fmt.Sprintf("oci://registry.replicated.com/replicated-sdk-e2e/%s/test-chart", channelSlug), "--version", "0.1.0", "--set", "replicated.tlsCertSecretName=test-tls"})

out, err = ctr.Stdout(ctx)
if err != nil {
return fmt.Errorf("failed to upgrade chart enabling TLS: %w", err)
}
fmt.Println(out)

ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec(
[]string{
"kubectl", "get", "secrets",
})

out, err = ctr.Stdout(ctx)
if err != nil {
return fmt.Errorf("failed to get secrets: %w", err)
}

fmt.Println(out)

ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec(
[]string{
"kubectl", "get", "pods",
})

out, err = ctr.Stdout(ctx)
if err != nil {
return fmt.Errorf("failed to get pods: %w", err)
}

fmt.Println(out)

// wait for the pod to be ready
ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec(
[]string{
"kubectl", "wait",
"--for=condition=available",
"deployment/replicated",
"--timeout=1m",
})

out, err = ctr.Stdout(ctx)
if err != nil {
fmt.Printf("failed to wait for deployment to be ready after enabling TLS: %v\n", err)
// return err
}
fmt.Println(out)

// create a kubernetes deployment that runs a pod - the pod has a readiness probe that runs 'curl -k https://replicated.svc:3000/health'
// this will only pass if the replicated pod is ready and serving TLS traffic
deploymentYaml := `apiVersion: apps/v1
kind: Deployment
metadata:
name: replicated-ssl-test
spec:
replicas: 1
selector:
matchLabels:
app: replicated-ssl-test
template:
metadata:
labels:
app: replicated-ssl-test
spec:
containers:
- name: replicated-ssl-test
image: alpine/curl:latest
command: ["sleep", "500d"]
ports:
- containerPort: 3000
readinessProbe:
exec:
command: ["curl", "-k", "https://replicated:3000/health"]
initialDelaySeconds: 10
periodSeconds: 10`
deploymentSource := source.WithNewFile("/replicated-ssl-test.yaml", deploymentYaml)

ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithFile("/root/replicated-ssl-test.yaml", deploymentSource.File("/replicated-ssl-test.yaml")).
WithExec([]string{"kubectl", "apply", "-f", "/root/replicated-ssl-test.yaml"})
out, err = ctr.Stdout(ctx)
if err != nil {
// Get stderr to see the actual error
stderr, _ := ctr.Stderr(ctx)
return fmt.Errorf("failed to apply replicated-ssl-test deployment: %w\n\nStderr: %s\n\nStdout: %s", err, stderr, out)
}
fmt.Println(out)

// wait for the replicated-ssl-test deployment to be ready
ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec([]string{"kubectl", "wait", "--for=condition=available", "deployment/replicated-ssl-test", "--timeout=1m"})
out, err = ctr.Stdout(ctx)
if err != nil {
ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec([]string{"kubectl", "logs", "-p", "-l", "app.kubernetes.io/name=replicated"})
out, err2 := ctr.Stdout(ctx)
if err2 != nil {
return fmt.Errorf("failed to get logs for replicated deployment: %w", err2)
}
fmt.Println(out)

return fmt.Errorf("failed to wait for replicated deployment to be ready: %w", err)
}
fmt.Println(out)

// print the final pods
ctr = dag.Container().From("bitnami/kubectl:latest").
WithFile("/root/.kube/config", kubeconfigSource.File("/kubeconfig")).
WithEnvVariable("KUBECONFIG", "/root/.kube/config").
WithExec(
[]string{
"kubectl", "get", "pods", "-n", "default",
})
out, err = ctr.Stdout(ctx)
if err != nil {
return fmt.Errorf("failed to get pods: %w", err)
}
fmt.Println(out)

fmt.Printf("E2E test for distribution %s and version %s passed\n", distribution, version)
return nil
}
26 changes: 20 additions & 6 deletions dagger/replicated.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,17 @@ import (
"time"
)

func createAppTestRelease(
// createWrappedTestChart creates a test chart with the replicated dependency and returns the chart file
func createWrappedTestChart(
ctx context.Context,
source *dagger.Directory,
opServiceAccount *dagger.Secret,
sdkChartRepository string,
) (string, error) {
replicatedServiceAccount := mustGetSecret(ctx, opServiceAccount, "Replicated", "service_account", VaultDeveloperAutomation)

) (*dagger.File, error) {
source = source.Directory("test-chart")

chartYAML, err := source.File("Chart.yaml").Contents(ctx)
if err != nil {
return "", err
return nil, err
}

// append the dependency to the test-chart chart.yaml
Expand All @@ -41,6 +39,22 @@ dependencies:
WithExec([]string{"helm", "package", "."}).
File("test-chart-0.1.0.tgz")

return testChartFile, nil
}

func createAppTestRelease(
ctx context.Context,
source *dagger.Directory,
opServiceAccount *dagger.Secret,
sdkChartRepository string,
) (string, error) {
replicatedServiceAccount := mustGetSecret(ctx, opServiceAccount, "Replicated", "service_account", VaultDeveloperAutomation)

testChartFile, err := createWrappedTestChart(ctx, source, sdkChartRepository)
if err != nil {
return "", err
}

now := time.Now().Format("20060102150405")
channelName := fmt.Sprintf("automated-%s", now)

Expand Down
44 changes: 44 additions & 0 deletions dagger/testchart.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"context"
"dagger/replicated-sdk/internal/dagger"
"fmt"
"time"
)

// TestChart builds the SDK image and chart and wraps them in a test chart
func (m *ReplicatedSdk) TestChart(
ctx context.Context,

// +defaultPath="/"
source *dagger.Directory,
) error {
imageRegistry, imageRepository, imageTag, err := buildAndPushImageToTTL(ctx, source)
if err != nil {
return err
}
fmt.Printf("SDK image pushed to %s/%s:%s\n", imageRegistry, imageRepository, imageTag)

chart, err := buildAndPushChartToTTL(ctx, source, imageRegistry, imageRepository, imageTag)
if err != nil {
return err
}
fmt.Printf("SDK chart pushed to %s\n", chart)

wrappedChart, err := createWrappedTestChart(ctx, source, chart)
if err != nil {
return err
}

now := time.Now().Format("20060102150405")
chartRef := fmt.Sprintf("oci://ttl.sh/automated-%s/wrapped-chart", now)
chartFile := "/chart/test-chart-0.1.0.tgz"

_ = dag.Container().From("alpine/helm:latest").
WithFile("/chart/test-chart-0.1.0.tgz", wrappedChart).
WithExec([]string{"helm", "push", chartFile, chartRef})
fmt.Printf("\n\nWrapped chart pushed to %s:0.1.0\n\n", chartRef)

return nil
}
Loading