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 00000000000..baa9b229d58 --- /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 00000000000..4039796ebad --- /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 00000000000..274361e0fd2 --- /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()