Skip to content

Commit fab7f0d

Browse files
committed
Add simple autest and subsequent fixes
1 parent 0cbe04c commit fab7f0d

File tree

13 files changed

+530
-51
lines changed

13 files changed

+530
-51
lines changed

plugins/experimental/uri_signing/common.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ void PrintToStdErr(const char *fmt, ...);
3333
#else
3434

3535
#include "ts/ts.h"
36-
#define PluginDebug(...) TSDebug("uri_signing", PLUGIN_NAME " " __VA_ARGS__)
37-
#define PluginError(...) PluginDebug(__VA_ARGS__), TSError(PLUGIN_NAME " " __VA_ARGS__)
36+
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
37+
#define PluginDebug(fmt, ...) TSDebug(PLUGIN_NAME, "[%s:% 4d] %s(): " fmt, __FILENAME__, __LINE__, __func__, ##__VA_ARGS__);
38+
#define PluginError(fmt, ...) \
39+
PluginDebug(fmt, ##__VA_ARGS__); \
40+
TSError("[%s:% 4d] %s(): " fmt, __FILENAME__, __LINE__, __func__, ##__VA_ARGS__);
3841

3942
#endif

plugins/experimental/uri_signing/config.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ read_config(const char *path)
289289
PluginDebug("Found Id in the config: %s", cfg->id);
290290
}
291291
}
292-
json_decref(id_json);
293292

294293
json_t *strip_json = json_object_get(jwks, "strip_token");
295294
if (strip_json) {

plugins/experimental/uri_signing/parse.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ cjose_jws_t *
3131
get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName, char *strip_uri, size_t buff_ct, size_t *strip_ct)
3232
{
3333
/* Reserved characters as defined by the URI Generic Syntax RFC: https://tools.ietf.org/html/rfc3986#section-2.2 */
34-
static const char *reserved_string = ":/?#[]@!$&\'()*+,;=";
35-
static const char *sub_delim_string = "!$&\'()*+,;=";
34+
static char const *const reserved_string = ":/?#[]@!$&\'()*+,;=";
35+
static char const *const sub_delim_string = "!$&\'()*+,;=";
3636

3737
/* If param name ends in reserved character this will be treated as the termination symbol when parsing for package. Default is
3838
* '='. */

plugins/experimental/uri_signing/parse.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include <stdlib.h>
2020

2121
struct _cjose_jws_int;
22+
23+
/* For now strip_ct returns size of string *including* the null terminator */
2224
struct _cjose_jws_int *get_jws_from_uri(const char *uri, size_t uri_ct, const char *paramName, char *strip_uri, size_t buff_ct,
2325
size_t *strip_ct);
2426
struct _cjose_jws_int *get_jws_from_cookie(const char **cookie, size_t *cookie_ct, const char *paramName);

plugins/experimental/uri_signing/python_signer/uri_signer.py

Lines changed: 93 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# "License"); you may not use this file except in compliance
99
# with the License. You may obtain a copy of the License at
1010
#
11-
# http://www.apache.org/licenses/LICENSE-2.0
11+
# http://www.apache.org/licenses/LICENSE-2.0
1212
#
1313
# Unless required by applicable law or agreed to in writing, software
1414
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,49 +26,107 @@
2626
from jose import jwk, jwt
2727

2828
def main():
29-
parser = argparse.ArgumentParser()
30-
parser.add_argument('-c', '--config',
31-
help="Configuration File",
32-
required=True)
33-
parser.add_argument('-u', '--uri',
34-
help="URI to sign",
35-
required=True)
36-
args = parser.parse_args()
29+
parser = argparse.ArgumentParser()
30+
parser.add_argument('-c', '--config',
31+
help="Configuration File",
32+
required=True)
33+
parser.add_argument('-u', '--uri',
34+
help="URI to sign",
35+
required=True)
3736

38-
with open(args.config, 'r') as f:
39-
config = json.load(f)
37+
# helpers
38+
parser.add_argument('--key_index', type=int, nargs=1)
39+
parser.add_argument('--token_lifetime', type=int, nargs=1)
4040

41-
keys = config["keys"]
41+
# override arguments -- claims
42+
parser.add_argument('--aud', nargs=1)
43+
parser.add_argument('--cdniets', type=int, nargs=1)
44+
parser.add_argument('--cdnistd', type=int, nargs=1)
45+
parser.add_argument('--cdnistt', type=int, nargs=1)
46+
parser.add_argument('--exp', type=int, nargs=1)
47+
parser.add_argument('--iss', nargs=1)
4248

43-
# Randomly select a key
49+
# override arguments -- key
50+
parser.add_argument('--alg', nargs=1)
51+
parser.add_argument('--k', nargs=1)
52+
parser.add_argument('--kid', nargs=1)
53+
parser.add_argument('--kty', nargs=1)
54+
55+
args = parser.parse_args()
56+
57+
with open(args.config, 'r') as f:
58+
config = json.load(f)
59+
60+
keys = config["keys"]
61+
62+
# Select a key, either explicitly or randomly
63+
key_index = 0
64+
if args.key_index:
65+
key_index = args.key_index[0]
66+
print("args key_index " + str(key_index))
67+
else:
4468
key_index = random.randint(0,len(keys)-1)
45-
print("Using Key: " + str(keys[key_index]["kid"]) + " to sign URI.")
46-
key = keys[key_index]
69+
print("randomizing key index")
70+
71+
print("Using key_index " + str(key_index))
72+
73+
print("Using Key: " + str(keys[key_index]["kid"]) + " to sign URI.")
74+
key = keys[key_index]
75+
76+
# Build Out claimset
77+
claimset = {}
78+
if "iss" in config.keys():
79+
claimset["iss"] = config["iss"]
80+
81+
if "token_lifetime" in config.keys():
82+
claimset["exp"] = int(time.time()) + config["token_lifetime"]
83+
else:
84+
claimset["exp"] = int(time.time()) + 30
85+
86+
if "aud" in config.keys():
87+
claimset["aud"] = config["aud"]
88+
89+
if "cdnistt" in config.keys():
90+
if config["cdnistt"]:
91+
claimset["cdnistt"] = 1
92+
if "cdniets" in config.keys():
93+
claimset["cdniets"] = config["cdniets"]
94+
else:
95+
claimset["cdniets"] = 30
96+
97+
98+
# process override args - simple
99+
if args.iss:
100+
claimset["iss"] = args.iss[0]
101+
if args.exp:
102+
claimset["exp"] = args.exp[0]
103+
if args.aud:
104+
claimset["aud"] = args.aud[0]
47105

48-
# Build Out claimset
49-
claimset = {}
50-
if ("iss" in config.keys()):
51-
claimset["iss"] = config["iss"]
106+
# process override args - complex
107+
if args.cdnistt:
108+
claimset["cdnistt"] = args.cdnistt[0]
52109

53-
if ("token_lifetime" in config.keys()):
54-
claimset["exp"] = int(time.time()) + config["token_lifetime"]
55-
else:
56-
claimset["exp"] = int(time.time()) + 30
110+
if "cdnistt" in config.keys():
111+
if args.cdniets:
112+
claimset["cdniets"] = arg.cdniets[0]
57113

58-
if("aud" in config.keys()):
59-
claimset["aud"] = config["aud"]
114+
# specific key overrides
115+
if args.alg:
116+
key["alg"] = args.alg[0]
117+
if args.kid:
118+
key["kid"] = args.kid[0]
119+
if args.kty:
120+
key["kty"] = args.kty[0]
121+
if args.k:
122+
key["k"] = args.k[0]
60123

61-
if("cdnistt" in config.keys()):
62-
if config["cdnistt"]:
63-
claimset["cdnistt"] = 1
64-
if("cdniets" in config.keys()):
65-
claimset["cdniets"] = config["cdniets"]
66-
else:
67-
claimset["cdniets"] = 30
124+
print(claimset)
125+
print(key)
68126

69-
Token = jwt.encode(claimset,key,algorithm=key["alg"])
127+
Token = jwt.encode(claimset,key,algorithm=key["alg"])
70128

71-
print("Signed URL: " + args.uri + "?urisigning=" + Token)
129+
print("Signed URL: " + args.uri + "?URISigningPackage=" + Token)
72130

73131
if __name__ == "__main__":
74-
main()
132+
main()

plugins/experimental/uri_signing/uri_signing.c

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,23 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s
6262

6363
TSDebug(PLUGIN_NAME, "Initializing remap function of %s -> %s with config from %s", argv[0], argv[1], argv[2]);
6464

65-
const char *install_dir = TSInstallDirGet();
66-
size_t config_file_ct = snprintf(NULL, 0, "%s/%s/%s", install_dir, "etc/trafficserver", argv[2]);
67-
char *config_file = malloc(config_file_ct + 1);
68-
(void)snprintf(config_file, config_file_ct + 1, "%s/%s/%s", install_dir, "etc/trafficserver", argv[2]);
65+
char const *const fname = argv[2];
66+
67+
if (0 == strlen(fname)) {
68+
snprintf(errbuf, errbuf_size, "[TSRemapNewKeyInstance] - Invalid config file name for %s -> %s", argv[0], argv[1]);
69+
return TS_ERROR;
70+
}
71+
72+
char *config_file = NULL;
73+
if ('/' == fname[0]) {
74+
config_file = strdup(fname);
75+
} else {
76+
char const *const config_dir = TSConfigDirGet();
77+
size_t const config_file_ct = snprintf(NULL, 0, "%s/%s", config_dir, fname);
78+
config_file = malloc(config_file_ct + 1);
79+
(void)snprintf(config_file, config_file_ct + 1, "%s/%s", config_dir, fname);
80+
}
81+
6982
TSDebug(PLUGIN_NAME, "config file name: %s", config_file);
7083
struct config *cfg = read_config(config_file);
7184
if (!cfg) {
@@ -159,8 +172,9 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
159172
const char *url = NULL;
160173
char *strip_uri = NULL;
161174
TSRemapStatus status = TSREMAP_NO_REMAP;
175+
bool checked_auth = false;
162176

163-
const char *package = "URISigningPackage";
177+
static char const *const package = "URISigningPackage";
164178

165179
TSMBuffer mbuf;
166180
TSMLoc ul;
@@ -207,7 +221,11 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
207221
field = TSMimeHdrFieldFind(buffer, hdr, "Cookie", 6);
208222
if (field == TS_NULL_MLOC) {
209223
TSHandleMLocRelease(buffer, TS_NULL_MLOC, hdr);
210-
goto fail;
224+
if (!checked_auth) {
225+
goto check_auth;
226+
} else {
227+
goto fail;
228+
}
211229
}
212230

213231
const char *client_cookie;
@@ -218,7 +236,11 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
218236
TSHandleMLocRelease(buffer, TS_NULL_MLOC, hdr);
219237

220238
if (!client_cookie || !client_cookie_ct) {
221-
goto fail;
239+
if (!checked_auth) {
240+
goto check_auth;
241+
} else {
242+
goto fail;
243+
}
222244
}
223245
size_t client_cookie_sz_ct = client_cookie_ct;
224246
check_more_cookies:
@@ -246,11 +268,15 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
246268
cjose_jws_t *map_jws = get_jws_from_uri(map_url, map_url_ct, package, map_strip_uri, map_strip_size, &map_strip_ct);
247269
cjose_jws_release(map_jws);
248270

249-
char *strip_uri_start = &map_strip_uri[0];
250-
char *strip_uri_end = &map_strip_uri[map_strip_ct];
251-
PluginDebug("Stripping token from upstream url to: %s", strip_uri_start);
271+
char const *strip_uri_start = map_strip_uri;
252272

253-
TSParseResult parse_rc = TSUrlParse(rri->requestBufp, rri->requestUrl, (const char **)&strip_uri_start, strip_uri_end);
273+
/* map_strip_uri is null terminated */
274+
size_t const mlen = strlen(strip_uri_start);
275+
char const *strip_uri_end = strip_uri_start + mlen;
276+
277+
PluginDebug("Stripping token from upstream url to: %.*s", (int)mlen, strip_uri_start);
278+
279+
TSParseResult parse_rc = TSUrlParse(rri->requestBufp, rri->requestUrl, &strip_uri_start, strip_uri_end);
254280
if (map_url != NULL) {
255281
TSfree(map_url);
256282
}
@@ -266,8 +292,10 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
266292
}
267293
}
268294
}
295+
check_auth:
269296
/* Check auth_dir and pass through if configured */
270297
if (uri_matches_auth_directive((struct config *)ih, url, url_ct)) {
298+
PluginDebug("Auth directive matched for %.*s", url_ct, url);
271299
if (url != NULL) {
272300
TSfree((void *)url);
273301
}
@@ -276,6 +304,8 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
276304
}
277305
return TSREMAP_NO_REMAP;
278306
}
307+
checked_auth = true;
308+
279309
if (!jws) {
280310
goto fail;
281311
}

tests/Pipfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ gunicorn = "*"
3434
httpbin = "*"
3535
microserver = ">=1.0.4"
3636
jsonschema = "*"
37+
python-jose = "*"
3738

3839
[requires]
3940
python_version = "3"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"issuer": {
3+
"id": "issuer",
4+
"renewal_kid": "1",
5+
"strip_token": true,
6+
"auth_directives": [
7+
{
8+
"auth": "allow",
9+
"uri": "regex:.*crossdomain.xml"
10+
}
11+
],
12+
"keys": [
13+
{
14+
"alg": "HS256",
15+
"k": "SECRET00",
16+
"kid": "0",
17+
"kty": "oct"
18+
},
19+
{
20+
"alg": "HS256",
21+
"k": "SECRET01",
22+
"kid": "1",
23+
"kty": "oct"
24+
}
25+
]
26+
}
27+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
``
2+
> GET `` HTTP/1.1
3+
> User-Agent: curl/``
4+
> Host: somehost``
5+
> Accept: */*
6+
> Proxy-Connection: ``
7+
``
8+
< HTTP/1.1 200 OK
9+
< Content-Length: ``
10+
< Date: ``
11+
< Proxy-Connection: ``
12+
< Server: ATS/``
13+
``
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
``
2+
> GET `` HTTP/1.1
3+
> User-Agent: curl/``
4+
> Host: somehost``
5+
> Accept: */*
6+
> Proxy-Connection: ``
7+
``
8+
< HTTP/1.1 403 Forbidden
9+
< Date: ``
10+
< Proxy-Connection: ``
11+
< Server: ATS/``
12+
< Cache-Control: no-store
13+
< Content-Type: text/html
14+
< Content-Language: en
15+
< Content-Length: ``
16+
``

0 commit comments

Comments
 (0)