From eb564466297aa441fc78363ed4fc53cfddd77c0e Mon Sep 17 00:00:00 2001 From: Todd L Miller Date: Thu, 14 Sep 2023 15:39:56 -0500 Subject: [PATCH 1/5] Add simple, manual test of the asynch interface; it requires a valid scitoken for an uncached issuer. --- test/CMakeLists.txt | 15 +++++ test/asynch.cc | 130 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 test/asynch.cc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 772ba1c..20e1f62 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -19,3 +19,18 @@ add_test( COMMAND ${CMAKE_CURRENT_BINARY_DIR}/scitokens-gtest ) + + +# +# Simple, interactive test of the asynchronous interface. Requires +# network access to do anything meaningful. +# +add_executable( scitokens-asynch-test asynch.cc ) +target_link_libraries( scitokens-asynch-test SciTokens ) + +add_test( + NAME + asynch + COMMAND + ${CMAKE_CURRENT_BINARY_DIR}/scitokens-asynch-test +) diff --git a/test/asynch.cc b/test/asynch.cc new file mode 100644 index 0000000..71b6126 --- /dev/null +++ b/test/asynch.cc @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include + +#include "../src/scitokens.h" + +void +usage( const char * self ) { + fprintf( stderr, "usage: %s encoded-scitoken\n", self ); +} + +void +print_claim( SciToken & token, const char * claim ) { + char * value; + char * error; + int rv = scitoken_get_claim_string( + token, claim, & value, & error + ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_get_claim_string('%s') failed: %s\n", claim, error ); + // exit( -2 ); + return; + } + fprintf( stdout, "%s = %s\n", claim, value ); +} + + +int +main( int argc, char ** argv) { + if( argc < 2 ) { usage(argv[0]); exit(-1); } + const char * encoded = argv[1]; + + int rv; + char * error; + SciToken token; + +/* + // Synchronous. + rv = scitoken_deserialize( encoded, & token, NULL, & error ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_deserialize() failed: %s\n", error ); + exit( -2 ); + } + // scitoken_destroy( token ); +*/ + + // The asynchronous API doesn't work like the synchronous API, and + // requires that deserialization profile be set before it starts + // working. This is probably a bug, but there's another bug where + // the default value for the profile causes a throw. *sigh* + + // Asynchronous API. + SciTokenStatus status; + rv = scitoken_deserialize_start( + encoded, & token, NULL, & status, & error + ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_deserialize_start() failed: %s\n", error ); + exit( -2 ); + } + if( status == NULL ) { + fprintf( stderr, "scitoken_deserialize_start() returned a token\n" ); + exit( 1 ); + } + + + do { + fd_set * read_fds = NULL; + rv = scitoken_status_get_read_fd_set( & status, & read_fds, & error ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_status_get_read_fd_set() failed: %s\n", error ); + exit( -2 ); + } + + fd_set * write_fds = NULL; + rv = scitoken_status_get_write_fd_set( & status, & write_fds, & error ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_status_get_write_fd_set() failed: %s\n", error ); + exit( -2 ); + } + + fd_set * except_fds = NULL; + rv = scitoken_status_get_exc_fd_set( & status, & except_fds, & error ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_status_get_exc_fd_set() failed: %s\n", error ); + exit( -2 ); + } + + int max_fds; + rv = scitoken_status_get_max_fd( & status, & max_fds, & error ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_status_get_max_fds() failed: %s\n", error ); + exit( -2 ); + } + + struct timeval time_out{1, 0}; + int s = select( max_fds + 1, read_fds, write_fds, except_fds, & time_out ); + if( s == -1 ) { + fprintf( stderr, "select() failed: %s (%d)\n", strerror(errno), errno ); + exit( -4 ); + } else if( s == 0 ) { + fprintf( stderr, "select() timed out, checking for progress.\n" ); + } + + fprintf( stderr, "Calling scitoken_deserialize_continue()...\n" ); + rv = scitoken_deserialize_continue( & token, & status, & error ); + if( rv != 0 ) { + fprintf( stderr, "scitoken_deserialize_continue() failed: %s\n", error ); + exit( -3 ); + } + } while( status != NULL ); + + + print_claim(token, "ver"); + print_claim(token, "aud"); + print_claim(token, "iss"); + // Not a string. + // print_claim(token, "exp"); + // Not a string. + // print_claim(token, "iat"); + // Not a string. + // print_claim(token, "nbf"); + print_claim(token, "jti"); + + scitoken_destroy( token ); + return 0; +} From 141b29c1fd263da65a1a45690eee7c5e71ef8b45 Mon Sep 17 00:00:00 2001 From: Todd L Miller Date: Fri, 15 Sep 2023 13:05:07 -0500 Subject: [PATCH 2/5] Add a script which fetches a valid token from demo.scitokens.org and invokes the test with it. --- test/asynch.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 test/asynch.py diff --git a/test/asynch.py b/test/asynch.py new file mode 100755 index 0000000..e078881 --- /dev/null +++ b/test/asynch.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import os +import json +import requests +import subprocess +import sys + + +def get_demo_token(payload: dict): + data = json.dumps({'algorithm': "ES256", 'payload': payload}) + resp = requests.post("https://demo.scitokens.org/issue", data=data) + return resp.text + + +demo_payload = { + "ver": "scitoken:2.0", + "aud": "https://demo.scitokens.org", + "iss": "https://demo.scitokens.org", +} +demo_token = get_demo_token(demo_payload) + +try: + scitokens_cache = os.path.expanduser('~/.cache/scitokens/scitokens_cpp.sqllite') + os.unlink(scitokens_cache) +except OSError: + pass +except FileNotFoundError: + pass + +rv = subprocess.run( + ['test/scitokens-asynch-test', demo_token], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + timeout=5, + universal_newlines=True, +) + +print(rv.stdout) +sys.exit(rv.returncode) From e9098de6addd55342d9a2c11675d39bd30f14d02 Mon Sep 17 00:00:00 2001 From: Todd L Miller Date: Fri, 15 Sep 2023 13:32:15 -0500 Subject: [PATCH 3/5] Add a script to automatically drive the asynch C code; don't use the user's key cache. --- test/CMakeLists.txt | 6 +++++- test/asynch.cc | 29 ++++++++++++----------------- test/asynch.py | 6 ++---- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 20e1f62..8ffe4e3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -28,9 +28,13 @@ add_test( add_executable( scitokens-asynch-test asynch.cc ) target_link_libraries( scitokens-asynch-test SciTokens ) +# This can't be the right to do specify this, and it also doesn't +# handle aysnch.py being updated correctly. +file(COPY asynch.py DESTINATION ${CMAKE_BINARY_DIR}/test) + add_test( NAME asynch COMMAND - ${CMAKE_CURRENT_BINARY_DIR}/scitokens-asynch-test + ${CMAKE_CURRENT_BINARY_DIR}/asynch.py ) diff --git a/test/asynch.cc b/test/asynch.cc index 71b6126..050e6e4 100644 --- a/test/asynch.cc +++ b/test/asynch.cc @@ -37,20 +37,21 @@ main( int argc, char ** argv) { char * error; SciToken token; -/* - // Synchronous. - rv = scitoken_deserialize( encoded, & token, NULL, & error ); + + // Set the cache to the CWD while testing. + char cache_path[FILENAME_MAX]; + if( getcwd(cache_path, sizeof(cache_path)) == NULL ) { + fprintf( stderr, "Failed to determine cwd, aborting.\n" ); + exit( -5 ); + } + + const char * key = "keycache.cache_home"; + rv = scitoken_config_set_str( key, cache_path, & error ); if( rv != 0 ) { - fprintf( stderr, "scitoken_deserialize() failed: %s\n", error ); - exit( -2 ); + fprintf( stderr, "Failed to set %s: %s, aborting.\n", key, cache_path ); + exit( -5 ); } - // scitoken_destroy( token ); -*/ - // The asynchronous API doesn't work like the synchronous API, and - // requires that deserialization profile be set before it starts - // working. This is probably a bug, but there's another bug where - // the default value for the profile causes a throw. *sigh* // Asynchronous API. SciTokenStatus status; @@ -117,12 +118,6 @@ main( int argc, char ** argv) { print_claim(token, "ver"); print_claim(token, "aud"); print_claim(token, "iss"); - // Not a string. - // print_claim(token, "exp"); - // Not a string. - // print_claim(token, "iat"); - // Not a string. - // print_claim(token, "nbf"); print_claim(token, "jti"); scitoken_destroy( token ); diff --git a/test/asynch.py b/test/asynch.py index e078881..f71f1a0 100755 --- a/test/asynch.py +++ b/test/asynch.py @@ -21,15 +21,13 @@ def get_demo_token(payload: dict): demo_token = get_demo_token(demo_payload) try: - scitokens_cache = os.path.expanduser('~/.cache/scitokens/scitokens_cpp.sqllite') + scitokens_cache = f"{os.getcwd()}/scitokens/scitokens_cpp.sqllite" os.unlink(scitokens_cache) -except OSError: - pass except FileNotFoundError: pass rv = subprocess.run( - ['test/scitokens-asynch-test', demo_token], + ['./scitokens-asynch-test', demo_token], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=5, From e334259cb22185f027ea1477629ca35fdda2be44 Mon Sep 17 00:00:00 2001 From: Derek Weitzel Date: Mon, 2 Oct 2023 13:00:30 -0500 Subject: [PATCH 4/5] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- test/asynch.cc | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/test/asynch.cc b/test/asynch.cc index 050e6e4..e9a4e64 100644 --- a/test/asynch.cc +++ b/test/asynch.cc @@ -1,10 +1,10 @@ #include +#include #include #include +#include #include #include -#include - #include "../src/scitokens.h" void @@ -13,26 +13,25 @@ usage( const char * self ) { } void -print_claim( SciToken & token, const char * claim ) { - char * value; - char * error; - int rv = scitoken_get_claim_string( - token, claim, & value, & error - ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_get_claim_string('%s') failed: %s\n", claim, error ); - // exit( -2 ); +void print_claim(SciToken &token, const char *claim) { + char *value; + char *error; + int rv = scitoken_get_claim_string(token, claim, &value, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_get_claim_string('%s') failed: %s\n", claim, + error); return; } fprintf( stdout, "%s = %s\n", claim, value ); } -int -main( int argc, char ** argv) { - if( argc < 2 ) { usage(argv[0]); exit(-1); } - const char * encoded = argv[1]; - +int main(int argc, char **argv) { + if (argc < 2) { + usage(argv[0]); + exit(-1); + } + const char *encoded = argv[1]; int rv; char * error; SciToken token; From 4fc9ae69a714973e6a779e0149495ce3258b601c Mon Sep 17 00:00:00 2001 From: Derek Weitzel Date: Mon, 2 Oct 2023 13:16:57 -0500 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- test/asynch.cc | 119 +++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/test/asynch.cc b/test/asynch.cc index e9a4e64..0c57e70 100644 --- a/test/asynch.cc +++ b/test/asynch.cc @@ -8,9 +8,8 @@ #include "../src/scitokens.h" void -usage( const char * self ) { - fprintf( stderr, "usage: %s encoded-scitoken\n", self ); -} +void usage(const char *self) { + fprintf(stderr, "usage: %s encoded-scitoken\n", self); void void print_claim(SciToken &token, const char *claim) { @@ -23,7 +22,7 @@ void print_claim(SciToken &token, const char *claim) { return; } fprintf( stdout, "%s = %s\n", claim, value ); -} + fprintf(stdout, "%s = %s\n", claim, value); int main(int argc, char **argv) { @@ -34,91 +33,93 @@ int main(int argc, char **argv) { const char *encoded = argv[1]; int rv; char * error; - SciToken token; + char *error; - // Set the cache to the CWD while testing. char cache_path[FILENAME_MAX]; if( getcwd(cache_path, sizeof(cache_path)) == NULL ) { - fprintf( stderr, "Failed to determine cwd, aborting.\n" ); - exit( -5 ); - } + if (getcwd(cache_path, sizeof(cache_path)) == NULL) { + fprintf(stderr, "Failed to determine cwd, aborting.\n"); + exit(-5); const char * key = "keycache.cache_home"; - rv = scitoken_config_set_str( key, cache_path, & error ); - if( rv != 0 ) { - fprintf( stderr, "Failed to set %s: %s, aborting.\n", key, cache_path ); - exit( -5 ); - } + const char *key = "keycache.cache_home"; + rv = scitoken_config_set_str(key, cache_path, &error); + if (rv != 0) { + fprintf(stderr, "Failed to set %s: %s, aborting.\n", key, cache_path); + exit(-5); - // Asynchronous API. SciTokenStatus status; rv = scitoken_deserialize_start( - encoded, & token, NULL, & status, & error - ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_deserialize_start() failed: %s\n", error ); - exit( -2 ); - } + rv = scitoken_deserialize_start(encoded, &token, NULL, &status, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_deserialize_start() failed: %s\n", error); + exit(-2); if( status == NULL ) { - fprintf( stderr, "scitoken_deserialize_start() returned a token\n" ); - exit( 1 ); - } + if (status == NULL) { + fprintf(stderr, "scitoken_deserialize_start() returned a token\n"); + exit(1); - do { fd_set * read_fds = NULL; - rv = scitoken_status_get_read_fd_set( & status, & read_fds, & error ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_status_get_read_fd_set() failed: %s\n", error ); - exit( -2 ); - } + fd_set *read_fds = NULL; + rv = scitoken_status_get_read_fd_set(&status, &read_fds, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_status_get_read_fd_set() failed: %s\n", + error); + exit(-2); fd_set * write_fds = NULL; - rv = scitoken_status_get_write_fd_set( & status, & write_fds, & error ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_status_get_write_fd_set() failed: %s\n", error ); - exit( -2 ); - } + fd_set *write_fds = NULL; + rv = scitoken_status_get_write_fd_set(&status, &write_fds, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_status_get_write_fd_set() failed: %s\n", + error); + exit(-2); fd_set * except_fds = NULL; - rv = scitoken_status_get_exc_fd_set( & status, & except_fds, & error ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_status_get_exc_fd_set() failed: %s\n", error ); - exit( -2 ); - } + fd_set *except_fds = NULL; + rv = scitoken_status_get_exc_fd_set(&status, &except_fds, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_status_get_exc_fd_set() failed: %s\n", + error); + exit(-2); int max_fds; rv = scitoken_status_get_max_fd( & status, & max_fds, & error ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_status_get_max_fds() failed: %s\n", error ); - exit( -2 ); - } + rv = scitoken_status_get_max_fd(&status, &max_fds, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_status_get_max_fds() failed: %s\n", + error); + exit(-2); struct timeval time_out{1, 0}; - int s = select( max_fds + 1, read_fds, write_fds, except_fds, & time_out ); - if( s == -1 ) { - fprintf( stderr, "select() failed: %s (%d)\n", strerror(errno), errno ); - exit( -4 ); - } else if( s == 0 ) { - fprintf( stderr, "select() timed out, checking for progress.\n" ); - } + struct timeval time_out { + 1, 0 + }; + int s = select(max_fds + 1, read_fds, write_fds, except_fds, &time_out); + if (s == -1) { + fprintf(stderr, "select() failed: %s (%d)\n", strerror(errno), + errno); + exit(-4); + } else if (s == 0) { + fprintf(stderr, "select() timed out, checking for progress.\n"); fprintf( stderr, "Calling scitoken_deserialize_continue()...\n" ); - rv = scitoken_deserialize_continue( & token, & status, & error ); - if( rv != 0 ) { - fprintf( stderr, "scitoken_deserialize_continue() failed: %s\n", error ); - exit( -3 ); - } + fprintf(stderr, "Calling scitoken_deserialize_continue()...\n"); + rv = scitoken_deserialize_continue(&token, &status, &error); + if (rv != 0) { + fprintf(stderr, "scitoken_deserialize_continue() failed: %s\n", + error); + exit(-3); } while( status != NULL ); - - + } while (status != NULL); print_claim(token, "ver"); print_claim(token, "aud"); print_claim(token, "iss"); print_claim(token, "jti"); scitoken_destroy( token ); - return 0; + scitoken_destroy(token); }