Skip to content

Commit ea3aa04

Browse files
traeakjrushford
authored andcommitted
Add simple autest and subsequent fixes
1 parent 4bdabd5 commit ea3aa04

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
@@ -21,6 +21,8 @@
2121
#include <stdlib.h>
2222

2323
struct _cjose_jws_int;
24+
25+
/* For now strip_ct returns size of string *including* the null terminator */
2426
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,
2527
size_t *strip_ct);
2628
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,
@@ -25,49 +25,107 @@
2525
from jose import jwt
2626

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

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

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

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

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

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

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

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

68-
Token = jwt.encode(claimset,key,algorithm=key["alg"])
126+
Token = jwt.encode(claimset,key,algorithm=key["alg"])
69127

70-
print("Signed URL: " + args.uri + "?urisigning=" + Token)
128+
print("Signed URL: " + args.uri + "?URISigningPackage=" + Token)
71129

72130
if __name__ == "__main__":
73-
main()
131+
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)