Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions plugins/experimental/uri_signing/python_signer/README.md
Original file line number Diff line number Diff line change
@@ -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.
33 changes: 33 additions & 0 deletions plugins/experimental/uri_signing/python_signer/example_config.json
Original file line number Diff line number Diff line change
@@ -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"
}
]
}
74 changes: 74 additions & 0 deletions plugins/experimental/uri_signing/python_signer/uri_signer.py
Original file line number Diff line number Diff line change
@@ -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()