Skip to content

Commit f7be0ee

Browse files
map: Prevent output destinations overlap with Caddyfile shorthands (#4657)
1 parent f6900fc commit f7be0ee

File tree

2 files changed

+61
-28
lines changed

2 files changed

+61
-28
lines changed

caddyconfig/httpcaddyfile/httptype.go

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -88,34 +88,10 @@ func (st ServerType) Setup(inputServerBlocks []caddyfile.ServerBlock,
8888
return nil, warnings, err
8989
}
9090

91-
// replace shorthand placeholders (which are
92-
// convenient when writing a Caddyfile) with
93-
// their actual placeholder identifiers or
94-
// variable names
95-
replacer := strings.NewReplacer(
96-
"{dir}", "{http.request.uri.path.dir}",
97-
"{file}", "{http.request.uri.path.file}",
98-
"{host}", "{http.request.host}",
99-
"{hostport}", "{http.request.hostport}",
100-
"{port}", "{http.request.port}",
101-
"{method}", "{http.request.method}",
102-
"{path}", "{http.request.uri.path}",
103-
"{query}", "{http.request.uri.query}",
104-
"{remote}", "{http.request.remote}",
105-
"{remote_host}", "{http.request.remote.host}",
106-
"{remote_port}", "{http.request.remote.port}",
107-
"{scheme}", "{http.request.scheme}",
108-
"{uri}", "{http.request.uri}",
109-
"{tls_cipher}", "{http.request.tls.cipher_suite}",
110-
"{tls_version}", "{http.request.tls.version}",
111-
"{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}",
112-
"{tls_client_issuer}", "{http.request.tls.client.issuer}",
113-
"{tls_client_serial}", "{http.request.tls.client.serial}",
114-
"{tls_client_subject}", "{http.request.tls.client.subject}",
115-
"{tls_client_certificate_pem}", "{http.request.tls.client.certificate_pem}",
116-
"{tls_client_certificate_der_base64}", "{http.request.tls.client.certificate_der_base64}",
117-
"{upstream_hostport}", "{http.reverse_proxy.upstream.hostport}",
118-
)
91+
// replace shorthand placeholders (which are convenient
92+
// when writing a Caddyfile) with their actual placeholder
93+
// identifiers or variable names
94+
replacer := strings.NewReplacer(placeholderShorthands()...)
11995

12096
// these are placeholders that allow a user-defined final
12197
// parameters, but we still want to provide a shorthand
@@ -1265,6 +1241,58 @@ func encodeMatcherSet(matchers map[string]caddyhttp.RequestMatcher) (caddy.Modul
12651241
return msEncoded, nil
12661242
}
12671243

1244+
// placeholderShorthands returns a slice of old-new string pairs,
1245+
// where the left of the pair is a placeholder shorthand that may
1246+
// be used in the Caddyfile, and the right is the replacement.
1247+
func placeholderShorthands() []string {
1248+
return []string{
1249+
"{dir}", "{http.request.uri.path.dir}",
1250+
"{file}", "{http.request.uri.path.file}",
1251+
"{host}", "{http.request.host}",
1252+
"{hostport}", "{http.request.hostport}",
1253+
"{port}", "{http.request.port}",
1254+
"{method}", "{http.request.method}",
1255+
"{path}", "{http.request.uri.path}",
1256+
"{query}", "{http.request.uri.query}",
1257+
"{remote}", "{http.request.remote}",
1258+
"{remote_host}", "{http.request.remote.host}",
1259+
"{remote_port}", "{http.request.remote.port}",
1260+
"{scheme}", "{http.request.scheme}",
1261+
"{uri}", "{http.request.uri}",
1262+
"{tls_cipher}", "{http.request.tls.cipher_suite}",
1263+
"{tls_version}", "{http.request.tls.version}",
1264+
"{tls_client_fingerprint}", "{http.request.tls.client.fingerprint}",
1265+
"{tls_client_issuer}", "{http.request.tls.client.issuer}",
1266+
"{tls_client_serial}", "{http.request.tls.client.serial}",
1267+
"{tls_client_subject}", "{http.request.tls.client.subject}",
1268+
"{tls_client_certificate_pem}", "{http.request.tls.client.certificate_pem}",
1269+
"{tls_client_certificate_der_base64}", "{http.request.tls.client.certificate_der_base64}",
1270+
"{upstream_hostport}", "{http.reverse_proxy.upstream.hostport}",
1271+
}
1272+
}
1273+
1274+
// WasReplacedPlaceholderShorthand checks if a token string was
1275+
// likely a replaced shorthand of the known Caddyfile placeholder
1276+
// replacement outputs. Useful to prevent some user-defined map
1277+
// output destinations from overlapping with one of the
1278+
// predefined shorthands.
1279+
func WasReplacedPlaceholderShorthand(token string) string {
1280+
prev := ""
1281+
for i, item := range placeholderShorthands() {
1282+
// only look at every 2nd item, which is the replacement
1283+
if i%2 == 0 {
1284+
prev = item
1285+
continue
1286+
}
1287+
if strings.Trim(token, "{}") == strings.Trim(item, "{}") {
1288+
// we return the original shorthand so it
1289+
// can be used for an error message
1290+
return prev
1291+
}
1292+
}
1293+
return ""
1294+
}
1295+
12681296
// tryInt tries to convert val to an integer. If it fails,
12691297
// it downgrades the error to a warning and returns 0.
12701298
func tryInt(val interface{}, warnings *[]caddyconfig.Warning) int {

modules/caddyhttp/map/caddyfile.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error)
5656
if len(handler.Destinations) == 0 {
5757
return nil, h.Err("missing destination argument(s)")
5858
}
59+
for _, dest := range handler.Destinations {
60+
if shorthand := httpcaddyfile.WasReplacedPlaceholderShorthand(dest); shorthand != "" {
61+
return nil, h.Errf("destination %s conflicts with a Caddyfile placeholder shorthand", shorthand)
62+
}
63+
}
5964

6065
// mappings
6166
for h.NextBlock(0) {

0 commit comments

Comments
 (0)