oficina / home Public

Clone
git clone https://amadan.net/oficina/home

Plain git — no account needed to clone.

Download

Download this file

1package home
2
3import (
4 "crypto/sha256"
5 "encoding/base64"
6 "encoding/hex"
7 "encoding/json"
8 "os"
9 "testing"
10
11 assertioncrypto "amadan.net/rastrillo/rastrillo/crypto"
12)
13
14func runtimeEnv(t *testing.T) (string, string) {
15 t.Helper()
16 setSecretEnv(t, nil)
17 for _, k := range []string{"HOME_ROSTER_MODE", "HOME_ROSTER_KEY"} {
18 t.Setenv(k, "")
19 os.Unsetenv(k)
20 }
21 for _, k := range []string{"HOME_APP_PREVIEW_ORIGINS", "HOME_APP_PREVIEW_ORIGINS_BASE64", "HOME_DOCS_PREVIEW_ORIGIN", "HOME_CONSUMERS_BASE64", "HOME_ASSERTION_KEYS_BASE64", "HOME_ROLE", "HOME_ASSERTION_KEY", "HOME_ASSERTION_KEYS", "HOME_CONSUMERS", "HOME_CREDENTIAL_ORIGIN", "HOME_DIRECTORY_ORIGIN"} {
22 t.Setenv(k, "")
23 }
24 t.Setenv("HOME_CREDENTIAL_ORIGIN", Origin)
25 t.Setenv("HOME_DIRECTORY_ORIGIN", directoryOrigin)
26 key, err := assertioncrypto.Generate()
27 if err != nil {
28 t.Fatal(err)
29 }
30 raw, err := assertioncrypto.MarshalKeypair(key)
31 if err != nil {
32 t.Fatal(err)
33 }
34 sum := sha256.Sum256(key.SignPub())
35 keys, _ := json.Marshal(map[string]string{hex.EncodeToString(sum[:]): base64.StdEncoding.EncodeToString(key.SignPub())})
36 return base64.StdEncoding.EncodeToString(raw), string(keys)
37}
38func TestRuntimeKeepsLegacyAndRequiresExplicitRoles(t *testing.T) {
39 runtimeEnv(t)
40 cfg, err := LoadRuntime("home.db", quietLogger())
41 if err != nil || cfg.role != "" || cfg.secrets.Sealer == nil {
42 t.Fatal("legacy config broken", err)
43 }
44 t.Setenv("HOME_ROLE", "typo")
45 if _, err = LoadRuntime("home.db", quietLogger()); err != errExchangeConfig {
46 t.Fatal("unknown role accepted")
47 }
48}
49func TestDirectoryRuntimeNeedsNoCredentialMaterial(t *testing.T) {
50 _, keys := runtimeEnv(t)
51 t.Setenv("HOME_ROLE", "directory")
52 t.Setenv("HOME_ASSERTION_KEYS", keys)
53 for _, k := range []string{"HOME_PEPPER", "HOME_SIGNIN_KEY", "CARLOS_SMTP_HOST", "CARLOS_SMTP_FROM", "CARLOS_SMTP_PASS"} {
54 t.Setenv(k, "")
55 }
56 cfg, err := LoadRuntime("directory.db", quietLogger())
57 if err != nil {
58 t.Fatal(err)
59 }
60 if cfg.signer != nil || len(cfg.secrets.Pepper) != 0 || cfg.secrets.Mailer != nil {
61 t.Fatal("directory holds credentials")
62 }
63 t.Setenv("HOME_ASSERTION_KEY", "present")
64 if _, err = LoadRuntime("directory.db", quietLogger()); err != errExchangeConfig {
65 t.Fatal("directory accepted credential private signing material")
66 }
67}
68func TestCredentialRuntimeValidatesManifestAndSigningKey(t *testing.T) {
69 private, _ := runtimeEnv(t)
70 t.Setenv("HOME_ROLE", "credential")
71 t.Setenv("HOME_ASSERTION_KEY", private)
72 t.Setenv("HOME_CONSUMERS", `{"directory":"https://oficina.works","docs":"https://blue.docs.oficina.works"}`)
73 cfg, err := LoadRuntime("home.db", quietLogger())
74 if err != nil || cfg.signer == nil || len(cfg.consumers) != 2 {
75 t.Fatal("valid signer refused", err)
76 }
77 for _, manifest := range []string{`null`, `{}`, `{"directory":"https://evil.invalid"}`, `{"directory":"https://oficina.works","docs":"https://id.oficina.works"}`, `{"directory":"https://oficina.works","directory":"https://oficina.works"}`, `{"directory":"https://oficina.works","bad id":"https://docs.example.com"}`, `{"directory":"https://oficina.works","docs":"https://0x"}`} {
78 t.Setenv("HOME_CONSUMERS", manifest)
79 if _, err = LoadRuntime("home.db", quietLogger()); err != errExchangeConfig {
80 t.Fatal("bad manifest accepted")
81 }
82 }
83 t.Setenv("HOME_CONSUMERS", `{"directory":"https://oficina.works"}`)
84 for _, key := range []string{"", "bad", base64.StdEncoding.EncodeToString([]byte(`{"sign_priv_d":"00","box_priv_d":"0101010101010101010101010101010101010101010101010101010101010101"}`))} {
85 t.Setenv("HOME_ASSERTION_KEY", key)
86 if _, err = LoadRuntime("home.db", quietLogger()); err != errExchangeConfig {
87 t.Fatal("invalid signing key accepted")
88 }
89 }
90}
91func TestDirectoryRuntimeRefusesMalformedKeys(t *testing.T) {
92 runtimeEnv(t)
93 t.Setenv("HOME_ROLE", "directory")
94 for _, keys := range []string{"", `null`, `{}`, `{"k":"AAAA"}`, `{"k":"AAAA","k":"AAAA"}`} {
95 t.Setenv("HOME_ASSERTION_KEYS", keys)
96 if _, err := LoadRuntime("directory.db", quietLogger()); err != errExchangeConfig {
97 t.Fatal("invalid verification keys accepted")
98 }
99 }
100}
101
102func TestRuntimeEncodedPlatformConfiguration(t *testing.T) {
103 private, keys := runtimeEnv(t)
104 t.Setenv("HOME_ROLE", "directory")
105 t.Setenv("HOME_ASSERTION_KEYS_BASE64", base64.StdEncoding.EncodeToString([]byte(keys)))
106 if _, err := LoadRuntime("directory.db", quietLogger()); err != nil {
107 t.Fatal(err)
108 }
109 t.Setenv("HOME_ASSERTION_KEYS", keys)
110 if _, err := LoadRuntime("directory.db", quietLogger()); err != errExchangeConfig {
111 t.Fatal("ambiguous keys accepted")
112 }
113 t.Setenv("HOME_ASSERTION_KEYS", "")
114 for _, bad := range []string{"%%%", base64.StdEncoding.EncodeToString([]byte(keys)) + "\n", base64.StdEncoding.EncodeToString([]byte(`{"key":null}`))} {
115 t.Setenv("HOME_ASSERTION_KEYS_BASE64", bad)
116 if _, err := LoadRuntime("directory.db", quietLogger()); err != errExchangeConfig {
117 t.Fatal("bad encoded keys accepted")
118 }
119 }
120 t.Setenv("HOME_ROLE", "credential")
121 t.Setenv("HOME_ASSERTION_KEY", private)
122 manifest := `{"directory":"https://oficina.works"}`
123 t.Setenv("HOME_CONSUMERS_BASE64", base64.StdEncoding.EncodeToString([]byte(manifest)))
124 if _, err := LoadRuntime("credential.db", quietLogger()); err != nil {
125 t.Fatal(err)
126 }
127 t.Setenv("HOME_CONSUMERS", manifest)
128 if _, err := LoadRuntime("credential.db", quietLogger()); err != errExchangeConfig {
129 t.Fatal("ambiguous manifest accepted")
130 }
131}
132