quorate/services/stalwart/cmd/controller/public_test.go

219 lines
6.8 KiB
Go
Raw Normal View History

package main
import (
"bytes"
"encoding/json"
"io"
"slices"
"strings"
"testing"
"text/template"
"gopkg.in/yaml.v3"
)
func TestAccountStaticFrontend(t *testing.T) {
deployment := serviceDeployment(t, "k8s/normal/server/deploy.yaml")
for _, container := range deployment.Spec.Template.Spec.Containers {
if container.Name != "account-web" {
continue
}
prefix, digest, pinned := strings.Cut(container.Image, "@sha256:")
if !pinned || prefix != "registry.quorate.internal/quorate/mail-keys" || !hexValue(digest, 64) {
t.Fatal("account frontend does not pin the custom UI image")
}
if len(container.Command) != 0 || len(container.Args) != 0 {
t.Fatal("account frontend overrides the image entrypoint")
}
for _, mount := range container.VolumeMounts {
if mount.MountPath == "/etc/nginx/nginx.conf" {
t.Fatal("account frontend overrides the static UI routing")
}
}
return
}
t.Fatal("account frontend is absent")
}
func TestAdminAPIKeepsIngress(t *testing.T) {
var route struct {
Spec struct {
Hostnames []string `yaml:"hostnames"`
Rules []struct {
BackendRefs []struct {
Name string `yaml:"name"`
Port int `yaml:"port"`
} `yaml:"backendRefs"`
} `yaml:"rules"`
} `yaml:"spec"`
}
if err := yaml.Unmarshal(serviceFiles(t, "k8s/normal/gateway/admin.yaml"), &route); err != nil {
t.Fatal(err)
}
if !slices.Equal(route.Spec.Hostnames, []string{"mail.quorate.internal"}) || len(route.Spec.Rules) != 1 {
t.Fatal("internal administration route is absent")
}
backends := route.Spec.Rules[0].BackendRefs
if len(backends) != 1 || backends[0].Name != "stalwart-admin" || backends[0].Port != 8080 {
t.Fatal("internal administration route does not target the management API")
}
var operations []struct {
Object string `json:"object"`
Value json.RawMessage `json:"value"`
}
if err := json.Unmarshal(serviceFiles(t, "k8s/base/plan.json"), &operations); err != nil {
t.Fatal(err)
}
for _, operation := range operations {
if operation.Object != "Application" {
continue
}
var apps map[string]struct {
Enabled bool `json:"enabled"`
}
if err := json.Unmarshal(operation.Value, &apps); err != nil {
t.Fatal(err)
}
if app, present := apps["bundled-webui"]; !present || len(apps) != 1 || app.Enabled {
t.Fatal("built-in WebUI default is not explicitly disabled")
}
return
}
t.Fatal("account application declaration is absent")
}
func TestAccountPublicConfig(t *testing.T) {
decoder := yaml.NewDecoder(bytes.NewReader(serviceFiles(t, "k8s/base/vault/identity.yaml")))
for {
var secret struct {
Metadata struct {
Name string `yaml:"name"`
} `yaml:"metadata"`
Spec struct {
Destination struct {
Transformation struct {
ExcludeRaw bool `yaml:"excludeRaw"`
Excludes []string `yaml:"excludes"`
Templates map[string]struct {
Text string `yaml:"text"`
} `yaml:"templates"`
} `yaml:"transformation"`
} `yaml:"destination"`
} `yaml:"spec"`
}
if err := decoder.Decode(&secret); err == io.EOF {
t.Fatal("public account config projection is absent")
} else if err != nil {
t.Fatal(err)
}
if secret.Metadata.Name != "mail-web" {
continue
}
transform := secret.Spec.Destination.Transformation
if !transform.ExcludeRaw || len(transform.Excludes) != 1 || transform.Excludes[0] != ".*" || len(transform.Templates) != 1 {
t.Fatal("account config projection includes raw identity metadata")
}
functions := template.FuncMap{
"get": func(values map[string]string, key string) string { return values[key] },
"dict": func(values ...string) map[string]string {
result := make(map[string]string)
for index := 0; index < len(values); index += 2 {
result[values[index]] = values[index+1]
}
return result
},
"toJson": func(value any) (string, error) {
encoded, err := json.Marshal(value)
return string(encoded), err
},
}
parsed, err := template.New("config").Funcs(functions).Parse(transform.Templates["config.json"].Text)
if err != nil {
t.Fatal(err)
}
var output bytes.Buffer
if err := parsed.Execute(&output, map[string]any{"Secrets": map[string]string{
"issuer_url": "https://identity.example.invalid", "account_client_id": "synthetic-account",
"audience": "synthetic-project", "client_secret": "synthetic-machine-secret",
}}); err != nil {
t.Fatal(err)
}
var config map[string]string
if err := json.Unmarshal(output.Bytes(), &config); err != nil {
t.Fatal(err)
}
if len(config) != 3 || config["issuer"] != "https://identity.example.invalid" || config["clientId"] != "synthetic-account" || config["scope"] != "openid profile urn:zitadel:iam:org:project:id:synthetic-project:aud" {
t.Fatalf("public account config = %#v", config)
}
break
}
var deployment struct {
Spec struct {
Template struct {
Spec struct {
Volumes []struct {
Name string `yaml:"name"`
Secret *struct {
SecretName string `yaml:"secretName"`
Items []struct {
Key string `yaml:"key"`
Path string `yaml:"path"`
} `yaml:"items"`
} `yaml:"secret"`
} `yaml:"volumes"`
Containers []struct {
Name string `yaml:"name"`
VolumeMounts []struct {
Name string `yaml:"name"`
MountPath string `yaml:"mountPath"`
SubPath string `yaml:"subPath"`
ReadOnly bool `yaml:"readOnly"`
} `yaml:"volumeMounts"`
} `yaml:"containers"`
} `yaml:"spec"`
} `yaml:"template"`
} `yaml:"spec"`
}
if err := yaml.Unmarshal(serviceFiles(t, "k8s/normal/server/deploy.yaml"), &deployment); err != nil {
t.Fatal(err)
}
secrets := make(map[string]string)
configFound := false
for _, volume := range deployment.Spec.Template.Spec.Volumes {
if volume.Secret == nil {
continue
}
secret := volume.Secret
secrets[volume.Name] = secret.SecretName
if volume.Name != "account-config" {
continue
}
configFound = true
if secret.SecretName != "mail-web" || len(secret.Items) != 1 || secret.Items[0].Key != "config.json" || secret.Items[0].Path != "config.json" {
t.Fatal("account config volume projects identity material beyond its public config")
}
}
if !configFound {
t.Fatal("account config volume is absent")
}
for _, container := range deployment.Spec.Template.Spec.Containers {
if container.Name != "account-web" {
continue
}
mounted := false
for _, mount := range container.VolumeMounts {
secret := secrets[mount.Name]
if secret != "" && secret != "mail-web" && secret != "stalwart-tls" {
t.Fatal("account frontend mounts an automation identity")
}
if mount.Name == "account-config" {
mounted = mount.MountPath == "/run/config" && mount.SubPath == "" && mount.ReadOnly
}
}
if !mounted {
t.Fatal("account frontend lacks a read-only public config projection")
}
return
}
t.Fatal("account frontend is absent")
}