This is an automated email from the ASF dual-hosted git repository. zwoop pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit f85548b9d6d0699b18e5cbeb23cdda1078f04f1b Author: Dylan Souza <dylan_so...@comcast.com> AuthorDate: Wed Oct 23 11:41:00 2019 -0600 Add Example URI Signer Python Script Provide an example script to be used in conjunction with the uri signing plugin. This script is meant to serve as an example of how to get started with uri signing and could be useful in testing various configs. (cherry picked from commit 3632eb748de4556dd87a66925ef2ace9a2b2c3fa) --- .../uri_signing/python_signer/README.md | 36 +++++++++++ .../uri_signing/python_signer/example_config.json | 33 ++++++++++ .../uri_signing/python_signer/uri_signer.py | 74 ++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/plugins/experimental/uri_signing/python_signer/README.md b/plugins/experimental/uri_signing/python_signer/README.md new file mode 100644 index 0000000..baa9b22 --- /dev/null +++ b/plugins/experimental/uri_signing/python_signer/README.md @@ -0,0 +1,36 @@ +Python URI Signer +================== + +Given a configuration file and a URI, this python script will generate a signed URI according to the URI signing protocol outlined [here](https://tools.ietf.org/html/draft-ietf-cdni-uri-signing-16): + +The script takes a config file and a uri as command line arguments. It picks one of the keys located in the json file at random +and embeds a valid JWT as a query string parameter into the uri and prints this new signed URI to standard out. + +** Disclaimer ** +Please note that this script is provided as a very simple example of how to implement a signer should not be considered production ready. + +Requirements +------ + +[python-jose](https://pypi.org/project/python-jose/) library must be installed (pip install python-jose). + +Config +------ + +The config file should be a JSON object that contains the following: + + - `iss`: A string representing the issuer of the token + - `token_lifetime`: The lifetime of the token in seconds. Expiry of the token is calculated as now + token_lifetime + - `aud`: A string representing the intended audience of the token. + - `cdnistt`: Boolean value which if set to true uses cookie signed token transport, allowing the validator of the token to + to issue subsequent tokens via set cookie headers. + - `cdniets`: Must be set if using cdnistt. Provides means of setting Expiry Times when generating subsequent tokens. It denotes + the number of seconds to be added to the time at which the JWT is verified that gives the value of the Expiry Time claim of the + next signed JWT. + - `keys`: A list of json objects, each one representing a key. Each key should have the following attributes: + - `alg`: The Cryptographic algorithm to be used with the key. + - `kid`: The key identifier + - `kty`: The key type + - `k`: The key itself + +example_config.json can be used as a template for the configuration file. diff --git a/plugins/experimental/uri_signing/python_signer/example_config.json b/plugins/experimental/uri_signing/python_signer/example_config.json new file mode 100644 index 0000000..4039796 --- /dev/null +++ b/plugins/experimental/uri_signing/python_signer/example_config.json @@ -0,0 +1,33 @@ +{ + "iss": "Example Issuer", + "token_lifetime": 90, + "aud": "Caching Software", + "cdnistt": true, + "cdniets": 30, + "keys": [ + { + "alg": "HS256", + "kid": 0, + "kty": "oct", + "k": "SECRET1" + }, + { + "alg": "HS256", + "kid": 1, + "kty": "oct", + "k": "SECRET2" + }, + { + "alg": "HS256", + "kid": 2, + "kty": "oct", + "k": "SECRET3" + }, + { + "alg": "HS256", + "kid": 3, + "kty": "oct", + "k": "SECRET4" + } + ] +} diff --git a/plugins/experimental/uri_signing/python_signer/uri_signer.py b/plugins/experimental/uri_signing/python_signer/uri_signer.py new file mode 100755 index 0000000..274361e --- /dev/null +++ b/plugins/experimental/uri_signing/python_signer/uri_signer.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import argparse +import random +import time +import os + +# https://github.com/mpdavis/python-jose +from jose import jwk, jwt + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-c', '--config', + help="Configuration File", + required=True) + parser.add_argument('-u', '--uri', + help="URI to sign", + required=True) + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = json.load(f) + + keys = config["keys"] + + # Randomly select a key + key_index = random.randint(0,len(keys)-1) + print("Using Key: " + str(keys[key_index]["kid"]) + " to sign URI.") + key = keys[key_index] + + # Build Out claimset + claimset = {} + if ("iss" in config.keys()): + claimset["iss"] = config["iss"] + + if ("token_lifetime" in config.keys()): + claimset["exp"] = int(time.time()) + config["token_lifetime"] + else: + claimset["exp"] = int(time.time()) + 30 + + if("aud" in config.keys()): + claimset["aud"] = config["aud"] + + if("cdnistt" in config.keys()): + if config["cdnistt"]: + claimset["cdnistt"] = 1 + if("cdniets" in config.keys()): + claimset["cdniets"] = config["cdniets"] + else: + claimset["cdniets"] = 30 + + Token = jwt.encode(claimset,key,algorithm=key["alg"]) + + print("Signed URL: " + args.uri + "?urisigning=" + Token) + +if __name__ == "__main__": + main()