Files
mailgoserver/internal/dnspublish/gcloud_test.go
T

126 lines
4.2 KiB
Go

package dnspublish
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
// fakeGCloudServiceAccountJSON builds a syntactically valid (but not
// Google-registered) service account key whose token_uri points at tokenURL — enough
// for golang.org/x/oauth2/google.JWTConfigFromJSON to parse and for its JWT-signing
// flow to run end-to-end against a fake local token endpoint, with no real network or
// real Google credentials involved.
func fakeGCloudServiceAccountJSON(t *testing.T, tokenURL string) string {
t.Helper()
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatal(err)
}
der, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
t.Fatal(err)
}
keyPEM := pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: der})
body, err := json.Marshal(map[string]string{
"type": "service_account",
"project_id": "test-project",
"private_key_id": "kid1",
"private_key": string(keyPEM),
"client_email": "test@test-project.iam.gserviceaccount.com",
"token_uri": tokenURL,
})
if err != nil {
t.Fatal(err)
}
return string(body)
}
func TestSetTXTRecordGCloudCreatesWhenNoneExists(t *testing.T) {
var gotChangePath string
var gotChangeBody map[string]any
mux := http.NewServeMux()
mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte(`{"access_token":"fake-token","token_type":"Bearer","expires_in":3600}`))
})
mux.HandleFunc("/dns/v1/projects/test-project/managedZones", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"managedZones":[{"name":"my-zone","dnsName":"example.com."}]}`))
})
mux.HandleFunc("/dns/v1/projects/test-project/managedZones/my-zone/rrsets", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"rrsets":[]}`))
})
mux.HandleFunc("/dns/v1/projects/test-project/managedZones/my-zone/changes", func(w http.ResponseWriter, r *http.Request) {
gotChangePath = r.URL.Path
body, _ := io.ReadAll(r.Body)
json.Unmarshal(body, &gotChangeBody)
w.Write([]byte(`{"id":"1","status":"pending"}`))
})
srv := httptest.NewServer(mux)
defer srv.Close()
origGCloud := GCloudAPIBase
GCloudAPIBase = srv.URL
defer func() { GCloudAPIBase = origGCloud }()
creds := Credentials{
Provider: "gcloud", ZoneName: "example.com", GCloudProject: "test-project",
GCloudServiceAccountJSON: fakeGCloudServiceAccountJSON(t, srv.URL+"/token"),
}
if err := SetTXTRecord(creds, "selector._domainkey.example.com", `"v=DKIM1; k=rsa; p=abc"`); err != nil {
t.Fatal(err)
}
if gotChangePath == "" {
t.Fatal("expected a Changes.Create request, got none")
}
additions, _ := gotChangeBody["additions"].([]any)
if len(additions) != 1 {
t.Fatalf("expected exactly one addition, got %v", gotChangeBody)
}
added := additions[0].(map[string]any)
if added["name"] != "selector._domainkey.example.com." || fmt.Sprint(added["rrdatas"]) != "[\"v=DKIM1; k=rsa; p=abc\"]" {
t.Fatalf("unexpected addition: %+v", added)
}
if deletions, ok := gotChangeBody["deletions"]; ok && deletions != nil {
if arr, ok := deletions.([]any); ok && len(arr) != 0 {
t.Fatalf("expected no deletions when no record existed, got %v", deletions)
}
}
}
func TestSetTXTRecordGCloudNoZoneFound(t *testing.T) {
mux := http.NewServeMux()
mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"access_token":"fake-token","token_type":"Bearer","expires_in":3600}`))
})
mux.HandleFunc("/dns/v1/projects/test-project/managedZones", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{"managedZones":[]}`))
})
srv := httptest.NewServer(mux)
defer srv.Close()
orig := GCloudAPIBase
GCloudAPIBase = srv.URL
defer func() { GCloudAPIBase = orig }()
creds := Credentials{
Provider: "gcloud", ZoneName: "nope.example", GCloudProject: "test-project",
GCloudServiceAccountJSON: fakeGCloudServiceAccountJSON(t, srv.URL+"/token"),
}
err := SetTXTRecord(creds, "selector._domainkey.nope.example", `"v=DKIM1"`)
if err == nil {
t.Fatal("expected an error when no managed zone matches")
}
if !strings.Contains(err.Error(), "no managed zone found") {
t.Fatalf("unexpected error: %v", err)
}
}