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
9 changes: 8 additions & 1 deletion pkg/k8s/resources/transform_ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@ func InjectCA(ns string) Transformer {
return fmt.Errorf("generate CA: %w", err)
}

// One secret per bridge. Rename only suffixes the device ID, so a fixed
// name was shared by every bridge from a device: each create replaced the
// CA the others had mounted, concurrent creates raced to create it, and
// removing the bridge that last labeled it deleted it for all of them.
secretName := "bridge-ca"
if tc.BridgeName != "" {
secretName += "-" + tc.BridgeName
}

secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -51,7 +58,7 @@ func InjectCA(ns string) Transformer {
})

// Mount the secret into the deployment. The volume references
// secretName "bridge-ca" which SuffixNames + RewriteRefs will update.
// secretName, which SuffixNames + RewriteRefs will update.
deploy, err := findApplicationDeployment(b, tc.SourceName)
if err != nil {
return &DeploymentNotFoundError{Name: tc.SourceName, Namespace: tc.SourceNamespace}
Expand Down
83 changes: 83 additions & 0 deletions pkg/k8s/resources/transform_ca_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package resources

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/vercel/bridge/pkg/k8s/meta"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
)

// TestInjectCA_SecretPerBridge verifies that two bridges from one device get
// their own CA secrets, each labeled for, and mounted by, its own bridge. A
// shared secret let one bridge's create replace another's CA and its remove
// delete it.
func TestInjectCA_SecretPerBridge(t *testing.T) {
const suffix = "-dev123"
type bridged struct {
secretName, secretDeployLabel, mountedSecret string
}
bridge := func(bridgeName string) bridged {
bundle, err := SourceFromManifests(packTestManifests(t, map[string]string{"manifests.yaml": `apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: app:latest
`}))
require.NoError(t, err)

tc := &TransformContext{Context: context.Background(), DeviceID: "dev123", BridgeName: bridgeName, SourceName: "app", SourceNamespace: "default"}
require.NoError(t, Transform(tc, bundle, []Transformer{
InjectCA("default"),
Rename(func(name string) string {
if name == "app" {
return "bdg-" + bridgeName + suffix
}
return "bdg-" + name + suffix
}),
InjectLabels(),
RewriteRefs(),
}))

var out bridged
for _, r := range bundle.Resources {
switch obj := r.Object.(type) {
case *corev1.Secret:
out.secretName = obj.Name
out.secretDeployLabel = obj.Labels[meta.LabelBridgeDeployment]
case *appsv1.Deployment:
for _, v := range obj.Spec.Template.Spec.Volumes {
if v.Name == caSecretVolumeName {
out.mountedSecret = v.Secret.SecretName
}
}
}
}
return out
}

a, b := bridge("alpha"), bridge("beta")

assert.Equal(t, "bdg-bridge-ca-alpha"+suffix, a.secretName)
assert.Equal(t, "bdg-bridge-ca-beta"+suffix, b.secretName)
assert.Equal(t, "bdg-alpha"+suffix, a.secretDeployLabel, "removed with its own bridge")
assert.Equal(t, "bdg-beta"+suffix, b.secretDeployLabel, "removed with its own bridge")
assert.Equal(t, a.secretName, a.mountedSecret)
assert.Equal(t, b.secretName, b.mountedSecret)
}
Loading