Skip to content

Commit af99185

Browse files
committed
replace placeholders in auth_key
This allows the use of `{env.VARNAME}` in the auth_key value to populate from env variables, as well as the upcoming `{file.path/to/file}` to read auth keys from files. Signed-off-by: Will Norris <will@tailscale.com>
1 parent cde4f89 commit af99185

2 files changed

Lines changed: 60 additions & 36 deletions

File tree

module.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ func getServer(ctx caddy.Context, addr string) (*tsnetServerDestructor, error) {
118118
}
119119

120120
if host != "" {
121-
s.AuthKey = getAuthKey(host, app)
121+
if s.AuthKey, err = getAuthKey(host, app); err != nil {
122+
app.logger.Warn("error parsing auth key", zap.Error(err))
123+
}
122124
s.Ephemeral = getEphemeral(host, app)
123125

124126
// Set config directory for tsnet. By default, tsnet will use the name of the
@@ -145,28 +147,31 @@ func getServer(ctx caddy.Context, addr string) (*tsnetServerDestructor, error) {
145147
return s.(*tsnetServerDestructor), nil
146148
}
147149

148-
func getAuthKey(host string, app *TSApp) string {
150+
var repl = caddy.NewReplacer()
151+
152+
func getAuthKey(host string, app *TSApp) (string, error) {
149153
if app == nil {
150-
return ""
154+
return "", nil
151155
}
156+
152157
svr := app.Servers[host]
153158
if svr.AuthKey != "" {
154-
return svr.AuthKey
159+
return repl.ReplaceOrErr(svr.AuthKey, true, true)
155160
}
156161

157162
if app.DefaultAuthKey != "" {
158-
return app.DefaultAuthKey
163+
return repl.ReplaceOrErr(app.DefaultAuthKey, true, true)
159164
}
160165

161166
// Set authkey to "TS_AUTHKEY_<HOST>".
162167
// If empty, fall back to "TS_AUTHKEY".
163168
authKey := os.Getenv("TS_AUTHKEY_" + strings.ToUpper(host))
164169
if authKey != "" {
165170
app.logger.Warn("Relying on TS_AUTHKEY_{HOST} env var is deprecated. Set caddy config instead.", zap.Any("host", host))
166-
return authKey
171+
return authKey, nil
167172
}
168173

169-
return os.Getenv("TS_AUTHKEY")
174+
return os.Getenv("TS_AUTHKEY"), nil
170175
}
171176

172177
func getEphemeral(host string, app *TSApp) bool {

module_test.go

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,78 @@ package tscaddy
22

33
import (
44
"errors"
5-
"fmt"
65
"net"
7-
"strings"
86
"testing"
97

108
"github.com/caddyserver/caddy/v2"
119
"tailscale.com/util/must"
1210
)
1311

1412
func Test_GetAuthKey(t *testing.T) {
15-
16-
const testkey = "abcdefghijklmnopqrstuvwxyz"
17-
const testHostKey = "1234567890"
18-
const testenvkey = "zyxwvutsrqponmlkjihgfedca"
19-
const testHost = "unittest"
20-
13+
const host = "host"
2114
tests := map[string]struct {
22-
host string
23-
skipApp bool
24-
want string
15+
env map[string]string // env vars to set
16+
defaultKey string // default key in caddy config
17+
hostKey string // host key in caddy config
18+
want string
2519
}{
2620
"default key from environment": {
27-
want: testenvkey,
28-
skipApp: true,
29-
host: "testhost",
21+
env: map[string]string{"TS_AUTHKEY": "envkey"},
22+
want: "envkey",
3023
},
31-
"host key from module": {
32-
want: testHostKey,
33-
host: testHost,
24+
"default key from caddy": {
25+
env: map[string]string{"TS_AUTHKEY": "envkey"},
26+
defaultKey: "defaultkey",
27+
want: "defaultkey",
28+
},
29+
"default key from caddy placeholder": {
30+
env: map[string]string{
31+
"TS_AUTHKEY": "envkey",
32+
"MYKEY": "mykey",
33+
},
34+
defaultKey: "{env.MYKEY}",
35+
want: "mykey",
3436
},
3537
"host key from environment": {
36-
want: testHostKey,
37-
skipApp: true,
38-
host: testHost,
38+
env: map[string]string{"TS_AUTHKEY_HOST": "envhostkey"},
39+
want: "envhostkey",
40+
},
41+
"host key from caddy": {
42+
env: map[string]string{"TS_AUTHKEY": "envkey"},
43+
hostKey: "hostkey",
44+
want: "hostkey",
45+
},
46+
"host key from caddy placeholder": {
47+
env: map[string]string{"MYKEY": "mykey"},
48+
hostKey: "{env.MYKEY}",
49+
want: "mykey",
50+
},
51+
"empty key from empty env var": {
52+
hostKey: "{env.DOES_NOT_EXIST}",
53+
want: "",
54+
},
55+
"empty key from bad placeholder": {
56+
hostKey: "{bad.placeholder}",
57+
want: "",
3958
},
4059
}
4160
for name, tt := range tests {
4261
t.Run(name, func(t *testing.T) {
4362
app := &TSApp{
44-
Servers: make(map[string]TSServer),
63+
DefaultAuthKey: tt.defaultKey,
64+
Servers: make(map[string]TSServer),
4565
}
4666
app.Provision(caddy.Context{})
47-
if !tt.skipApp {
48-
app.DefaultAuthKey = testkey
49-
app.Servers[testHost] = TSServer{
50-
AuthKey: testHostKey,
67+
if tt.hostKey != "" {
68+
app.Servers[host] = TSServer{
69+
AuthKey: tt.hostKey,
5170
}
5271
}
53-
t.Setenv("TS_AUTHKEY", testenvkey)
54-
hostKey := fmt.Sprintf("TS_AUTHKEY_%s", strings.ToUpper(testHost))
55-
t.Setenv(hostKey, testHostKey)
72+
for k, v := range tt.env {
73+
t.Setenv(k, v)
74+
}
5675

57-
got := getAuthKey(tt.host, app)
76+
got, _ := getAuthKey(host, app)
5877
if got != tt.want {
5978
t.Errorf("GetAuthKey() = %v, want %v", got, tt.want)
6079
}

0 commit comments

Comments
 (0)