summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--auth-server-poc/src/app.py3
-rw-r--r--auth-server-poc/userdb.yaml (renamed from auth-server-poc/src/userdb.yaml)6
-rwxr-xr-xquickstart.sh7
-rwxr-xr-xsrc/main.py17
-rwxr-xr-xsrc/quickstart_test.sh5
-rw-r--r--src/test/test_api.py4
-rw-r--r--tools/jwt_producer.py64
8 files changed, 86 insertions, 34 deletions
diff --git a/README.md b/README.md
index 40fdb1f..d39b006 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,13 @@ We can also limit the number of results and skip N results forward with the para
curl -s -H "Authorization: Bearer $JWT" 'http://localhost:80/sc/v0/get?limit=5&skip=2' | json_pp -json_opt utf8,pretty
-There is also a convenience script `do-as` which simplifies performing actions as a particular user.
+## Tips and tricks
+
+There is a convenience script `do-as` which simplifies performing actions as a particular user.
+
+You can decode a JWT using jq by piping to `jq -r '.access_token | split(".") | .[0],.[1] | @base64d' | jq`. Full example:
+
+ curl http://localhost:8000/api/v1.0/auth -X POST -p -u user1:pwd | jq -r '.access_token | split(".") | .[0],.[1] | @base64d' | jq
## Development
@@ -91,9 +97,3 @@ There are two docker-compose files used for development:
- `auth-server-poc/docker-compose.yml` for the JWT server.
To apply changes, `source env-vars.sh` and do e.g. `docker-compose -f docker/docker-compose-dev.yaml up -d --build collector`.
-
-## JWT mechanics (work in progress)
-
-2021-11-24: Currently no checks except that the JWT is valid are performed when
-adding observations. When retrieving observations, the JWTs "domains" claim is
-used. In auth-server-poc, domains is hard-coded to `["sunet.se"]` as an example.
diff --git a/auth-server-poc/src/app.py b/auth-server-poc/src/app.py
index c7ba0d1..37a7030 100644
--- a/auth-server-poc/src/app.py
+++ b/auth-server-poc/src/app.py
@@ -16,6 +16,7 @@ jwt = JWTManager(app)
PEM_PRIVATE = "/opt/auth-server-poc/cert/private.pem"
PEM_PUBLIC = "/opt/auth-server-poc/cert/public.pem"
+USERDB_YAML = "/opt/auth-server-poc/userdb/userdb.yaml"
app.config["JWT_PRIVATE_KEY"] = open(PEM_PRIVATE).read()
app.config["JWT_PUBLIC_KEY"] = open(PEM_PUBLIC).read()
@@ -28,7 +29,7 @@ class AuthApi(Resource):
def post(self):
identity = request.environ.get("REMOTE_USER")
- db = authn.UserDB("userdb.yaml")
+ db = authn.UserDB(USERDB_YAML)
additional_claims = {
"type": "access",
"read": db.read_perms(identity),
diff --git a/auth-server-poc/src/userdb.yaml b/auth-server-poc/userdb.yaml
index c55773b..937328c 100644
--- a/auth-server-poc/src/userdb.yaml
+++ b/auth-server-poc/userdb.yaml
@@ -1,3 +1,9 @@
+usr:
+ authz:
+ sunet.se: rw
+ su.se: rw
+ kth.se: rw
+
user1:
authz:
sunet.se: r
diff --git a/quickstart.sh b/quickstart.sh
index edf8c43..950475b 100755
--- a/quickstart.sh
+++ b/quickstart.sh
@@ -22,12 +22,17 @@ fi
# Generate a default htpasswd file with a user "usr:pwd".
if [ ! -f ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd ]; then
- htpasswd -b -c ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user1 pwd
+ htpasswd -b -c ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd usr pwd
+ htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user1 pwd
htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user2 pwd
htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user3 pwd
htpasswd -b ${DOCKER_JWT_HTPASSWD_PATH}/.htpasswd user4 pwd
fi
+if [ ! -f ${DOCKER_JWT_HTPASSWD_PATH}/userdb.yaml ]; then
+ cp auth-server-poc/userdb.yaml ${DOCKER_JWT_HTPASSWD_PATH}/userdb.yaml
+fi
+
# Launch the containers.
docker-compose -f docker/docker-compose-dev.yaml up -d
docker-compose -f auth-server-poc/docker-compose.yml up -d
diff --git a/src/main.py b/src/main.py
index a65971d..d6f420f 100755
--- a/src/main.py
+++ b/src/main.py
@@ -31,6 +31,23 @@ async def mock_x_total_count_header(request: Request, call_next):
response.headers["X-Total-Count"] = "100"
return response
+<< << << < HEAD
+== == == =
+for i in range(10):
+ try:
+ db = DictDB()
+ except Exception:
+ print(
+ f'Database not responding, will try again soon. Attempt {i + 1} of 10.')
+ else:
+ break
+ time.sleep(1)
+else:
+ print('Database did not respond after 10 attempts, quitting.')
+ sys.exit(-1)
+
+>>>>>> > main
+
def get_pubkey():
try:
diff --git a/src/quickstart_test.sh b/src/quickstart_test.sh
index e81024f..3d4945e 100755
--- a/src/quickstart_test.sh
+++ b/src/quickstart_test.sh
@@ -5,7 +5,6 @@ export COUCHDB_PASSWORD=test
export DOCKER_JWT_PUBKEY_PATH="`pwd`/test/unittest_cert/"
export JWT_PUBKEY_PATH="`pwd`/test/unittest_cert/public.pem"
-export JWT_TOKEN="eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJ0eXBlIjoiYWNjZXNzIiwiZG9tYWlucyI6WyJzdW5ldC5zZSJdfQ._emWyVw-6qer5u65SitS8bZJas7l8bw4almnI1TB7DBnzNsch8ctU4btlgBpfJ2jbrvXZTIl8jXIcykO4crUrQ"
virtualenv=no
couchdb=no
@@ -49,8 +48,8 @@ mkdir test/unittest_cert
cat <<EOF > test/unittest_cert/public.pem
-----BEGIN PUBLIC KEY-----
-MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPW8bkkVIq4BX8eWwlUOUYbJhiGDv
-K/6xY5T0BsvV6pbMoIUfgeThVOq5I3CmXxLt+qyPska6ol9fTN7woZLsCg==
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGHX8ipqVWtr49TXyX0f/L4GPhEpg
+N0Erzy7hHkXVrkgKpnHSRLYWgbW4rscLoJAJeEv7Be5iH0TM8l09w8Q3wQ==
-----END PUBLIC KEY-----
EOF
diff --git a/src/test/test_api.py b/src/test/test_api.py
index cabe101..9d76e5e 100644
--- a/src/test/test_api.py
+++ b/src/test/test_api.py
@@ -9,9 +9,7 @@ from fastapi import FastAPI
from fastapi import testclient
client = testclient.TestClient(app)
-JWT_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJ0eXBlIjoiYWNjZXNzIiwi' + \
- 'ZG9tYWlucyI6WyJzdW5ldC5zZSJdfQ._emWyVw-6qer5u65SitS8bZJas7l8bw4almnI1' + \
- 'TB7DBnzNsch8ctU4btlgBpfJ2jbrvXZTIl8jXIcykO4crUrQ'
+JWT_TOKEN = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY0MjE2ODkyMCwianRpIjoiNjM0NGFiNjEtMTIzZC00YWMyLTk3YjMtYmVlYTE2M2JiMWMwIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6InVzZXIxIiwibmJmIjoxNjQyMTY4OTIwLCJyZWFkIjpbInN1bmV0LnNlIl0sIndyaXRlIjpbInN1bmV0LnNlIl19._bX9EHI9h0Vjw75UvYvypqaH3AmsgaATFSUSOT-cYLZHrfMlxios3emr7cyKw-OV_BN5h_XNyrMBV1gIoqAk3A'
JWT_HEADER = {'Authorization': f'Bearer {JWT_TOKEN}'}
diff --git a/tools/jwt_producer.py b/tools/jwt_producer.py
index ea033a6..a024c13 100644
--- a/tools/jwt_producer.py
+++ b/tools/jwt_producer.py
@@ -7,17 +7,30 @@ import jwt
def usage():
progname = sys.argv[0]
- print(f'{progname} -p <path to private key> ' +
- '-d <domain, for example sunet.se> ',
- '-t <type, can be access or scanner>')
+ print(f'Usage: {progname} [-p <path>] [-w <value>] [-r <value>]\n' +
+ ' -p <path to private key>\n' +
+ ' -w <write, comma separated list of domains>\n' +
+ ' -r <read, comma separated list of domains>\n' +
+ ' -e <print export statement')
sys.exit(0)
-def create_token(private_key, token_type, domain):
+def create_token(private_key, write_domains, read_domains):
+ write_claim = list()
+ read_claim = list()
+
+ if write_domains:
+ write_claim = write_domains.split(',')
+
+ if read_domains:
+ read_claim = read_domains.split(',')
+
payload = {
+ 'sub': 'test',
+ 'fresh': False,
'type': 'access',
- 'domains': [domain], # We'll just do one domain now
- 'user': token_type
+ 'write': write_claim,
+ 'read': read_claim
}
with open(private_key, "r") as fd:
@@ -27,27 +40,40 @@ def create_token(private_key, token_type, domain):
if __name__ == '__main__':
+ read_domains = None
+ write_domains = None
+ private_key = None
+ export = False
+
try:
- opts, args = getopt.getopt(sys.argv[1:], 'p:d:t:')
+ opts, args = getopt.getopt(sys.argv[1:], 'p:w:r:eh')
except getopt.GetoptError:
usage()
- if len(sys.argv) != 7:
- usage()
-
for opt, arg in opts:
if opt == '-p':
private_key = arg
- elif opt == '-d':
- domain = arg
- elif opt == '-t':
- token_type = arg
-
- if token_type != "access" and token_type != "scanner":
- usage()
+ elif opt == '-w':
+ write_domains = arg
+ elif opt == '-r':
+ read_domains = arg
+ elif opt == '-e':
+ export = True
+ elif opt == '-h':
+ usage()
else:
usage()
- token = create_token(private_key, token_type, domain).decode('utf-8')
+ if not private_key:
+ usage()
+
+ if not write_domains and not read_domains:
+ usage()
+
+ token = create_token(private_key, write_domains,
+ read_domains)
- print(f'{token}')
+ if export:
+ print(f'export JWT_TOKEN={token}')
+ else:
+ print(f'{token}')