Skip to content

Commit 4bf0cd7

Browse files
committed
Merge and lots of bug fixes for async
Merge branch 'master' of https://github.com/scitokens/scitokens-cpp into scitokens_async
2 parents 7858357 + aec994e commit 4bf0cd7

File tree

93 files changed

+34310
-1676
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+34310
-1676
lines changed

.github/workflows/ccpp.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ env:
1515
jobs:
1616
build:
1717

18-
runs-on: ubuntu-latest
19-
2018
strategy:
2119
matrix:
2220
external-gtest: [ YES, NO ]
21+
os: [ ubuntu-latest, ubuntu-22.04 ]
2322

24-
name: Build with external_gtest=${{ matrix.external-gtest }}
23+
runs-on: ${{ matrix.os }}
24+
name: Build with external_gtest=${{ matrix.external-gtest }} on ${{ matrix.os }}
2525

2626
steps:
2727
- uses: actions/checkout@v1

CMakeLists.txt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ project( scitokens-cpp
88

99
option( SCITOKENS_BUILD_UNITTESTS "Build the scitokens-cpp unit tests" OFF )
1010
option( SCITOKENS_EXTERNAL_GTEST "Use an external/pre-installed copy of GTest" OFF )
11-
option( SCITOKENS_WARNINGS_ARE_ERRORS "Turn compiler warnings into build errors" OFF)
1211

1312
set( CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}" )
1413

@@ -39,7 +38,6 @@ endif()
3938

4039
add_library(SciTokens SHARED src/scitokens.cpp src/scitokens_internal.cpp src/scitokens_cache.cpp)
4140
target_compile_features(SciTokens PUBLIC cxx_std_11) # Use at least C++11 for building and when linking to scitokens
42-
target_compile_options(SciTokens PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall $<$<BOOL:${SCITOKENS_WARNINGS_ARE_ERRORS}>:-Werror>>)
4341
target_include_directories(SciTokens PUBLIC ${JWT_CPP_INCLUDES} "${PROJECT_SOURCE_DIR}/src" PRIVATE ${CURL_INCLUDES} ${OPENSSL_INCLUDE_DIRS} ${LIBCRYPTO_INCLUDE_DIRS} ${SQLITE_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS})
4442

4543
target_link_libraries(SciTokens PUBLIC ${OPENSSL_LIBRARIES} ${LIBCRYPTO_LIBRARIES} ${CURL_LIBRARIES} ${SQLITE_LIBRARIES} ${UUID_LIBRARIES})
@@ -57,23 +55,18 @@ add_executable(scitokens-test src/test.cpp)
5755
#target_include_directories(scitokens-test PRIVATE "${PROJECT_SOURCE_DIR}" ${JWT_CPP_INCLUDES} ${CURL_INCLUDES} ${OPENSSL_INCLUDE_DIRS} ${LIBCRYPTO_INCLUDE_DIRS} ${SQLITE_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS})
5856
target_include_directories(scitokens-test PRIVATE "${PROJECT_SOURCE_DIR}" ${JWT_CPP_INCLUDES} ${LIBCRYPTO_INCLUDE_DIRS})
5957
target_link_libraries(scitokens-test SciTokens)
60-
target_compile_options(scitokens-test PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall $<$<BOOL:${SCITOKENS_WARNINGS_ARE_ERRORS}>:-Werror>>)
6158

6259
add_executable(scitokens-verify src/verify.cpp)
6360
target_link_libraries(scitokens-verify SciTokens)
64-
target_compile_options(scitokens-verify PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall $<$<BOOL:${SCITOKENS_WARNINGS_ARE_ERRORS}>:-Werror>>)
6561

6662
add_executable(scitokens-test-access src/test_access.cpp)
6763
target_link_libraries(scitokens-test-access SciTokens)
68-
target_compile_options(scitokens-test-access PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall $<$<BOOL:${SCITOKENS_WARNINGS_ARE_ERRORS}>:-Werror>>)
6964

7065
add_executable(scitokens-list-access src/list_access.cpp)
7166
target_link_libraries(scitokens-list-access SciTokens)
72-
target_compile_options(scitokens-list-access PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall $<$<BOOL:${SCITOKENS_WARNINGS_ARE_ERRORS}>:-Werror>>)
7367

7468
add_executable(scitokens-create src/create.cpp)
7569
target_link_libraries(scitokens-create SciTokens)
76-
target_compile_options(scitokens-create PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall $<$<BOOL:${SCITOKENS_WARNINGS_ARE_ERRORS}>:-Werror>>)
7770

7871
get_directory_property(TARGETS BUILDSYSTEM_TARGETS)
7972
install(

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Building
1515

1616
To build the `scitokens-cpp` library, the following dependencies are needed:
1717

18-
- [jwt-cpp](https://github.com/Thalhammer/jwt-cpp): A header-only C++ library for manipulating
18+
- [jwt-cpp] v0.5.0 or later (https://github.com/Thalhammer/jwt-cpp): A header-only C++ library for manipulating
1919
JWTs.
2020
- OpenSSL 1.0 or later.
2121
- `sqlite3`

configs/export-symbols

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ global:
33
scitoken*;
44
validator*;
55
enforcer*;
6+
keycache*;
67

78
local:
89
*;

src/scitokens.cpp

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,21 +284,37 @@ int scitoken_deserialize_start(const char *value, SciToken *token, char const* c
284284
*err_msg = strdup(exc.what());
285285
}
286286
delete real_token;
287+
*status_out = nullptr;
287288
return -1;
288289
}
290+
291+
// Check if we're done
292+
if (status->m_status->m_done) {
293+
*token = real_token;
294+
*status_out = nullptr;
295+
return 0;
296+
}
297+
289298
*token = real_token;
290299
*status_out = status.release();
291300
return 0;
292301
}
293302

294-
int scitoken_deserialize_continue(SciToken token, SciTokenStatus *status, char **err_msg) {
303+
int scitoken_deserialize_continue(SciToken *token, SciTokenStatus *status, char **err_msg) {
295304
if (token == nullptr) {
296305
if (err_msg) {*err_msg = strdup("Output token not provided");}
297306
return -1;
298307
}
308+
309+
299310
scitokens::SciToken *real_token = reinterpret_cast<scitokens::SciToken*>(token);
300311
std::unique_ptr<scitokens::SciTokenAsyncStatus> real_status(reinterpret_cast<scitokens::SciTokenAsyncStatus*>(*status));
301312

313+
if (*status == nullptr || real_status->m_status->m_done) {
314+
*status = nullptr;
315+
return 0;
316+
}
317+
302318
try {
303319
real_status = real_token->deserialize_continue(std::move(real_status));
304320
} catch (std::exception &exc) {
@@ -409,6 +425,18 @@ int validator_validate(Validator validator, SciToken scitoken, char **err_msg) {
409425
}
410426

411427

428+
int validator_set_time(Validator validator, time_t now, char **err_msg) {
429+
if (validator == nullptr) {
430+
if (err_msg) {*err_msg = strdup("Validator may not be a null pointer");}
431+
return -1;
432+
}
433+
auto real_validator = reinterpret_cast<scitokens::Validator*>(validator);
434+
435+
real_validator->set_now(std::chrono::system_clock::from_time_t(now));
436+
437+
return 0;
438+
}
439+
412440
Enforcer enforcer_create(const char *issuer, const char **audience_list, char **err_msg) {
413441
if (issuer == nullptr) {
414442
if (err_msg) {*err_msg = strdup("Issuer may not be a null pointer");}
@@ -478,6 +506,18 @@ Acl *convert_acls(scitokens::Enforcer::AclsList &acls_list, char **err_msg)
478506

479507
}
480508

509+
int enforcer_set_time(Enforcer enf, time_t now, char **err_msg) {
510+
if (enf == nullptr) {
511+
if (err_msg) {*err_msg = strdup("Enforcer may not be a null pointer");}
512+
return -1;
513+
}
514+
auto real_enf = reinterpret_cast<scitokens::Enforcer*>(enf);
515+
516+
real_enf->set_now(std::chrono::system_clock::from_time_t(now));
517+
518+
return 0;
519+
}
520+
481521

482522
int enforcer_generate_acls(const Enforcer enf, const SciToken scitoken, Acl **acls, char **err_msg) {
483523
if (enf == nullptr) {
@@ -621,7 +661,6 @@ int scitoken_status_get_timeout_val(const SciTokenStatus *status, time_t expiry_
621661
struct timeval timeout_internal = real_status->get_timeout_val(expiry_time);
622662
timeout->tv_sec = timeout_internal.tv_sec;
623663
timeout->tv_usec = timeout_internal.tv_usec;
624-
625664
return 0;
626665
}
627666

@@ -692,3 +731,66 @@ int scitoken_status_get_max_fd(const SciTokenStatus *status, int *max_fd, char *
692731
*max_fd = real_status->get_max_fd();
693732
return 0;
694733
}
734+
735+
736+
int keycache_refresh_jwks(const char *issuer, char **err_msg)
737+
{
738+
if (!issuer) {
739+
if (err_msg) {*err_msg = strdup("Issuer may not be a null pointer");}
740+
return -1;
741+
}
742+
try {
743+
if (!scitokens::Validator::refresh_jwks(issuer)) {
744+
if (err_msg) {*err_msg = strdup("Failed to refresh JWKS cache for issuer.");}
745+
return -1;
746+
}
747+
} catch (std::exception &exc) {
748+
if (err_msg) {*err_msg = strdup(exc.what());}
749+
return -1;
750+
}
751+
return 0;
752+
}
753+
754+
755+
int keycache_get_cached_jwks(const char *issuer, char **jwks, char **err_msg)
756+
{
757+
if (!issuer) {
758+
if (err_msg) {*err_msg = strdup("Issuer may not be a null pointer");}
759+
return -1;
760+
}
761+
if (!jwks) {
762+
if (err_msg) {*err_msg = strdup("JWKS output pointer may not be null.");}
763+
return -1;
764+
}
765+
try {
766+
*jwks = strdup(scitokens::Validator::get_jwks(issuer).c_str());
767+
} catch(std::exception &exc) {
768+
if (err_msg) {*err_msg = strdup(exc.what());}
769+
return -1;
770+
}
771+
return 0;
772+
}
773+
774+
775+
int keycache_set_jwks(const char *issuer, const char *jwks, char **err_msg)
776+
{
777+
if (!issuer) {
778+
if (err_msg) {*err_msg = strdup("Issuer may not be a null pointer");}
779+
return -1;
780+
}
781+
if (!jwks) {
782+
if (err_msg) {*err_msg = strdup("JWKS pointer may not be null.");}
783+
return -1;
784+
}
785+
try {
786+
if (!scitokens::Validator::store_jwks(issuer, jwks)) {
787+
if (err_msg) {*err_msg = strdup("Failed to set the JWKS cache for issuer.");}
788+
return -1;
789+
}
790+
} catch(std::exception &exc) {
791+
if (err_msg) {*err_msg = strdup(exc.what());}
792+
return -1;
793+
}
794+
return 0;
795+
}
796+

src/scitokens.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
#include <sys/select.h>
99

1010
#ifdef __cplusplus
11+
#include <ctime>
1112
extern "C" {
13+
#else
14+
#include <time.h>
1215
#endif
1316

1417
typedef void * SciTokenKey;
@@ -106,6 +109,17 @@ int scitoken_deserialize(const char *value, SciToken *token, char const* const*
106109
int scitoken_deserialize_start(const char *value, SciToken *token, char const* const* allowed_issuers,
107110
SciTokenStatus *status, char **err_msg);
108111

112+
/**
113+
* @brief Continue the deserialization process for a token, updating the status object.
114+
*
115+
* If the status object indicates that the token is complete, the token object will be
116+
* populated and the status object will be nullptr.
117+
*
118+
* @param token The token object, returned from scitoken_deserialize_start.
119+
* @param status Status object for the deserialize.
120+
* @param err_msg Destination for error message.
121+
* @return int 0 on success, -1 on error.
122+
*/
109123

110124
int scitoken_deserialize_continue(SciToken *token, SciTokenStatus *status, char **err_msg);
111125

@@ -121,6 +135,12 @@ Validator validator_create();
121135
*/
122136
void validator_set_token_profile(Validator, SciTokenProfile profile);
123137

138+
/**
139+
* Set the time to use with the validator. Useful if you want to see if the token would
140+
* have been valid at some time in the past.
141+
*/
142+
int validator_set_time(Validator validator, time_t now, char **err_msg);
143+
124144
int validator_add(Validator validator, const char *claim, StringValidatorFunction validator_func, char **err_msg);
125145

126146
int validator_add_critical_claims(Validator validator, const char **claims, char **err_msg);
@@ -142,6 +162,12 @@ void enforcer_destroy(Enforcer);
142162
*/
143163
void enforcer_set_validate_profile(Enforcer, SciTokenProfile profile);
144164

165+
/**
166+
* Set the time to use with the enforcer. Useful if you want to see if the token would
167+
* have been valid at some time in the past.
168+
*/
169+
int enforcer_set_time(Enforcer enf, time_t now, char **err_msg);
170+
145171
int enforcer_generate_acls(const Enforcer enf, const SciToken scitokens, Acl **acls, char **err_msg);
146172

147173
/**
@@ -196,6 +222,38 @@ int scitoken_status_get_exc_fd_set(SciTokenStatus *status, fd_set **exc_fd_set,
196222
*/
197223
int scitoken_status_get_max_fd(const SciTokenStatus *status, int *max_fd, char **err_msg);
198224

225+
/**
226+
* API for explicity managing the key cache.
227+
*
228+
* This manipulates the keycache for the current eUID.
229+
*/
230+
231+
232+
/**
233+
* Refresh the JWKS in the keycache for a given issuer; the refresh will occur
234+
* even if the JWKS is not otherwise due for updates.
235+
* - Returns 0 on success, nonzero on failure.
236+
*/
237+
int keycache_refresh_jwks(const char *issuer, char **err_msg);
238+
239+
/**
240+
* Retrieve the JWKS from the keycache for a given issuer.
241+
* - Returns 0 if successful, nonzero on failure.
242+
* - If the existing JWKS has expired - or does not exist - this does not trigger a new
243+
* download of the JWKS from the issuer. Instead, it will return a JWKS object with
244+
* an empty set of keys.
245+
* - `jwks` is an output variable set to the contents of the JWKS in the key cache.
246+
*/
247+
int keycache_get_cached_jwks(const char *issuer, char **jwks, char **err_msg);
248+
249+
/**
250+
* Replace any existing key cache entry with one provided by the user.
251+
* The expiration and next update time of the user-provided JWKS will utilize
252+
* the same rules as a download from an issuer with no explicit cache lifetime directives.
253+
* - `jwks` is value that will be set in the cache.
254+
*/
255+
int keycache_set_jwks(const char *issuer, const char *jwks, char **err_msg);
256+
199257
#ifdef __cplusplus
200258
}
201259
#endif

0 commit comments

Comments
 (0)