Skip to content

Commit dc2919b

Browse files
authored
Merge pull request #120 from jhiemstrawisc/cache-location-config
Cache location config
2 parents 3b183c1 + 6cb9b2c commit dc2919b

File tree

6 files changed

+256
-26
lines changed

6 files changed

+256
-26
lines changed

src/scitokens.cpp

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
#include <atomic>
22
#include <exception>
33
#include <string.h>
4-
4+
#include <sys/stat.h>
55

66
#include "scitokens.h"
77
#include "scitokens_internal.h"
88

99
/**
1010
* GLOBALS
1111
*/
12+
13+
// Cache timeout config
1214
std::atomic_int configurer::Configuration::m_next_update_delta{600};
1315
std::atomic_int configurer::Configuration::m_expiry_delta{4 * 24 * 3600};
1416

17+
// SciTokens cache home config
18+
std::shared_ptr<std::string> configurer::Configuration::m_cache_home =
19+
std::make_shared<std::string>("");
20+
1521
SciTokenKey scitoken_key_create(const char *key_id, const char *alg,
1622
const char *public_contents,
1723
const char *private_contents, char **err_msg) {
@@ -950,6 +956,10 @@ int keycache_set_jwks(const char *issuer, const char *jwks, char **err_msg) {
950956
}
951957

952958
int config_set_int(const char *key, int value, char **err_msg) {
959+
return scitoken_config_set_int(key, value, err_msg);
960+
}
961+
962+
int scitoken_config_set_int(const char *key, int value, char **err_msg) {
953963
if (!key) {
954964
if (err_msg) {
955965
*err_msg = strdup("A key must be provided.");
@@ -958,7 +968,6 @@ int config_set_int(const char *key, int value, char **err_msg) {
958968
}
959969

960970
std::string _key = key;
961-
962971
if (_key == "keycache.update_interval_s") {
963972
if (value < 0) {
964973
if (err_msg) {
@@ -970,8 +979,8 @@ int config_set_int(const char *key, int value, char **err_msg) {
970979
return 0;
971980
}
972981

973-
if (_key == "keycache.expiration_interval_s") {
974-
if (value < 0 ) {
982+
else if (_key == "keycache.expiration_interval_s") {
983+
if (value < 0) {
975984
if (err_msg) {
976985
*err_msg = strdup("Expiry interval must be positive.");
977986
}
@@ -990,6 +999,10 @@ int config_set_int(const char *key, int value, char **err_msg) {
990999
}
9911000

9921001
int config_get_int(const char *key, char **err_msg) {
1002+
return scitoken_config_get_int(key, err_msg);
1003+
}
1004+
1005+
int scitoken_config_get_int(const char *key, char **err_msg) {
9931006
if (!key) {
9941007
if (err_msg) {
9951008
*err_msg = strdup("A key must be provided.");
@@ -998,12 +1011,11 @@ int config_get_int(const char *key, char **err_msg) {
9981011
}
9991012

10001013
std::string _key = key;
1001-
10021014
if (_key == "keycache.update_interval_s") {
10031015
return configurer::Configuration::get_next_update_delta();
10041016
}
10051017

1006-
if (_key == "keycache.expiration_interval_s") {
1018+
else if (_key == "keycache.expiration_interval_s") {
10071019
return configurer::Configuration::get_expiry_delta();
10081020
}
10091021

@@ -1013,4 +1025,55 @@ int config_get_int(const char *key, char **err_msg) {
10131025
}
10141026
return -1;
10151027
}
1016-
}
1028+
}
1029+
1030+
int scitoken_config_set_str(const char *key, const char *value,
1031+
char **err_msg) {
1032+
if (!key) {
1033+
if (err_msg) {
1034+
*err_msg = strdup("A key must be provided.");
1035+
}
1036+
return -1;
1037+
}
1038+
1039+
std::string _key = key;
1040+
if (_key == "keycache.cache_home") {
1041+
auto rp = configurer::Configuration::set_cache_home(value);
1042+
if (!rp.first) { // There was an error, pass rp.second to err_msg
1043+
if (err_msg) {
1044+
*err_msg = strdup(rp.second.c_str());
1045+
}
1046+
return -1;
1047+
}
1048+
}
1049+
1050+
else {
1051+
if (err_msg) {
1052+
*err_msg = strdup("Key not recognized.");
1053+
}
1054+
return -1;
1055+
}
1056+
return 0;
1057+
}
1058+
1059+
int scitoken_config_get_str(const char *key, char **output, char **err_msg) {
1060+
if (!key) {
1061+
if (err_msg) {
1062+
*err_msg = strdup("A key must be provided.");
1063+
}
1064+
return -1;
1065+
}
1066+
1067+
std::string _key = key;
1068+
if (_key == "keycache.cache_home") {
1069+
*output = strdup(configurer::Configuration::get_cache_home().c_str());
1070+
}
1071+
1072+
else {
1073+
if (err_msg) {
1074+
*err_msg = strdup("Key not recognized.");
1075+
}
1076+
return -1;
1077+
}
1078+
return 0;
1079+
}

src/scitokens.h

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,24 +291,43 @@ int keycache_get_cached_jwks(const char *issuer, char **jwks, char **err_msg);
291291
int keycache_set_jwks(const char *issuer, const char *jwks, char **err_msg);
292292

293293
/**
294-
* API for managing scitokens configuration parameters.
294+
* APIs for managing scitokens configuration parameters.
295295
*/
296296

297+
// On its way to deprecation
298+
int config_set_int(const char *key, int value, char **err_msg);
299+
297300
/**
298-
* Update scitokens parameters.
301+
* Update scitokens int parameters.
299302
* Takes in key/value pairs and assigns the input value to whatever
300303
* configuration variable is indicated by the key.
301304
* Returns 0 on success, and non-zero for invalid keys or values.
302305
*/
303-
int config_set_int(const char *key, int value, char **err_msg);
306+
int scitoken_config_set_int(const char *key, int value, char **err_msg);
307+
308+
// on its way to deprecation
309+
int config_get_int(const char *key, char **err_msg);
304310

305311
/**
306-
* Get current scitokens parameters.
312+
* Get current scitokens int parameters.
307313
* Returns the value associated with the supplied input key on success, and -1
308-
* on failure This assumes there are no keys for which a negative return value
314+
* on failure. This assumes there are no keys for which a negative return value
309315
* is permissible.
310316
*/
311-
int config_get_int(const char *key, char **err_msg);
317+
int scitoken_config_get_int(const char *key, char **err_msg);
318+
319+
/**
320+
* Set current scitokens str parameters.
321+
* Returns 0 on success, nonzero on failure
322+
*/
323+
int scitoken_config_set_str(const char *key, const char *value, char **err_msg);
324+
325+
/**
326+
* Get current scitokens str parameters.
327+
* Returns 0 on success, nonzero on failure, and populates the value associated
328+
* with the input key to output.
329+
*/
330+
int scitoken_config_get_str(const char *key, char **output, char **err_msg);
312331

313332
#ifdef __cplusplus
314333
}

src/scitokens_cache.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ void initialize_cachedb(const std::string &keycache_file) {
4242

4343
/**
4444
* Get the Cache file location
45-
*
46-
* 1. $XDG_CACHE_HOME
47-
* 2. .cache subdirectory of home directory as returned by the password
45+
* 1. User-defined through config api
46+
* 2. $XDG_CACHE_HOME
47+
* 3. .cache subdirectory of home directory as returned by the password
4848
* database
4949
*/
5050
std::string get_cache_file() {
@@ -64,7 +64,16 @@ std::string get_cache_file() {
6464
home_dir += "/.cache";
6565
}
6666

67-
std::string cache_dir(xdg_cache_home ? xdg_cache_home : home_dir.c_str());
67+
// Figure out where to plop the cache based on priority
68+
std::string cache_dir;
69+
std::string configured_cache_dir =
70+
configurer::Configuration::get_cache_home();
71+
if (configured_cache_dir.length() > 0) { // The variable has been configured
72+
cache_dir = configured_cache_dir;
73+
} else {
74+
cache_dir = xdg_cache_home ? xdg_cache_home : home_dir.c_str();
75+
}
76+
6877
if (cache_dir.size() == 0) {
6978
return "";
7079
}

src/scitokens_internal.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <functional>
33
#include <memory>
44
#include <sstream>
5+
#include <sys/stat.h>
56

67
#include <jwt-cpp/base.h>
78
#include <jwt-cpp/jwt.h>
@@ -1064,3 +1065,89 @@ bool scitokens::Enforcer::scope_validator(const jwt::claim &claim,
10641065

10651066
return me->m_test_authz.empty();
10661067
}
1068+
1069+
// Configuration class functions
1070+
std::pair<bool, std::string>
1071+
configurer::Configuration::set_cache_home(const std::string dir_path) {
1072+
// If setting to "", then we should treat as though it is unsetting the
1073+
// config
1074+
if (dir_path.length() == 0) { // User is configuring to empty string
1075+
m_cache_home = std::make_shared<std::string>(dir_path);
1076+
return std::make_pair(true, "");
1077+
}
1078+
1079+
std::vector<std::string> path_components =
1080+
path_split(dir_path); // cleans any extraneous /'s
1081+
std::string cleaned_dir_path;
1082+
for (const auto &component :
1083+
path_components) { // add the / back to the path components
1084+
cleaned_dir_path += "/" + component;
1085+
}
1086+
1087+
// Check that the cache_home exists, and if not try to create it
1088+
auto rp = mkdir_and_parents_if_needed(
1089+
cleaned_dir_path); // Structured bindings not introduced until cpp 17
1090+
if (!rp.first) { //
1091+
std::string err_prefix{
1092+
"An issue was encountered with the provided cache home path: "};
1093+
return std::make_pair(false, err_prefix + rp.second);
1094+
}
1095+
1096+
// Now it exists and we can write to it, set the value and let
1097+
// scitokens_cache handle the rest
1098+
m_cache_home = std::make_shared<std::string>(cleaned_dir_path);
1099+
return std::make_pair(true, "");
1100+
}
1101+
1102+
std::string configurer::Configuration::get_cache_home() {
1103+
return *m_cache_home;
1104+
}
1105+
1106+
// bool configurer::Configuration::check_dir(const std::string dir_path) {
1107+
// struct stat info;
1108+
// return stat(dir_path.c_str(), &info) == 0 && (info.st_mode & S_IFDIR);
1109+
// }
1110+
1111+
std::pair<bool, std::string>
1112+
configurer::Configuration::mkdir_and_parents_if_needed(
1113+
const std::string dir_path) {
1114+
// SciTokens-cpp already makes assumptions about using Linux file paths,
1115+
// so making that assumption here as well.
1116+
1117+
// Using these perms because that's what the actual cache file uses in
1118+
// scitokens_cache
1119+
mode_t mode = 0700; // Maybe these permissions should be configurable?
1120+
1121+
int result;
1122+
std::string currentLevel;
1123+
std::vector<std::string> path_components = path_split(dir_path);
1124+
for (const auto &component : path_components) {
1125+
currentLevel += "/" + component;
1126+
result = mkdir(currentLevel.c_str(), mode);
1127+
if ((result < 0) && errno != EEXIST) {
1128+
std::string err_prefix{"There was an error while creating/checking "
1129+
"the directory: mkdir error: "};
1130+
return std::make_pair(false, err_prefix + strerror(errno));
1131+
}
1132+
}
1133+
1134+
return std::make_pair(true, "");
1135+
}
1136+
1137+
std::vector<std::string>
1138+
configurer::Configuration::path_split(std::string path) {
1139+
std::vector<std::string> path_components;
1140+
std::stringstream ss(path);
1141+
std::string component;
1142+
1143+
while (std::getline(ss, component, '/')) {
1144+
if (!component.empty()) {
1145+
path_components.push_back(component);
1146+
}
1147+
}
1148+
1149+
if (path_components[0] == "") {
1150+
path_components.erase(path_components.begin());
1151+
}
1152+
return path_components;
1153+
}

src/scitokens_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,17 @@ class Configuration {
4242
m_expiry_delta = _expiry_delta;
4343
}
4444
static int get_expiry_delta() { return m_expiry_delta; }
45+
static std::pair<bool, std::string> set_cache_home(const std::string cache_home);
46+
static std::string get_cache_home();
47+
4548
private:
4649
static std::atomic_int m_next_update_delta;
4750
static std::atomic_int m_expiry_delta;
51+
static std::shared_ptr<std::string> m_cache_home;
52+
// static bool check_dir(const std::string dir_path);
53+
static std::pair<bool, std::string>
54+
mkdir_and_parents_if_needed(const std::string dir_path);
55+
static std::vector<std::string> path_split(const std::string dir_path);
4856
};
4957
} // namespace configurer
5058

0 commit comments

Comments
 (0)