Enabled to load shared library for Credential and Token (#1927)

This commit is contained in:
Takeshi Nakatani 2022-10-22 10:42:07 +09:00 committed by GitHub
parent 9a4282208e
commit 6e89e69bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 592 additions and 20 deletions

View File

@ -310,6 +310,11 @@ AC_COMPILE_IFELSE(
]
)
dnl ----------------------------------------------
dnl dl library
dnl ----------------------------------------------
AC_CHECK_LIB([dl], [dlopen, dlclose, dlerror, dlsym], [], [AC_MSG_ERROR([Could not found dlopen, dlclose, dlerror and dlsym])])
dnl ----------------------------------------------
dnl build date
dnl ----------------------------------------------

View File

@ -284,6 +284,15 @@ This option instructs s3fs to use IBM IAM authentication. In this mode, the AWSA
\fB\-o\fR ibm_iam_endpoint (default is https://iam.cloud.ibm.com)
Sets the URL to use for IBM IAM authentication.
.TP
\fB\-o\fR credlib (default=\"\" which means disabled)
Specifies the shared library that handles the credentials containing the authentication token.
If this option is specified, the specified credential and token processing provided by the shared library ant will be performed instead of the built-in credential processing.
This option cannot be specified with passwd_file, profile, use_session_token, ecs, ibm_iam_auth, ibm_iam_endpoint, imdsv1only and iam_role option.
.TP
\fB\-o\fR credlib_opts (default=\"\" which means disabled)
Specifies the options to pass when the shared library specified in credlib is loaded and then initialized.
For the string specified in this option, specify the string defined by the shared library.
.TP
\fB\-o\fR use_xattr (default is not handling the extended attribute)
Enable to handle the extended attribute (xattrs).
If you set this option, you can use the extended attribute.

View File

@ -46,6 +46,11 @@ extern std::string endpoint;
extern std::string cipher_suites;
extern std::string instance_name;
//-------------------------------------------------------------------
// For weak attribute
//-------------------------------------------------------------------
#define S3FS_FUNCATTR_WEAK __attribute__ ((weak,unused))
#endif // S3FS_COMMON_H_
/*

View File

@ -3504,7 +3504,7 @@ static void s3fs_exit_fuseloop(int exit_status)
static void* s3fs_init(struct fuse_conn_info* conn)
{
S3FS_PRN_INIT_INFO("init v%s(commit:%s) with %s", VERSION, COMMIT_HASH_VAL, s3fs_crypt_lib_name());
S3FS_PRN_INIT_INFO("init v%s(commit:%s) with %s, credential-library(%s)", VERSION, COMMIT_HASH_VAL, s3fs_crypt_lib_name(), ps3fscred->GetCredFuncVersion(false));
// cache(remove cache dirs at first)
if(is_remove_cache && (!CacheFileStat::DeleteCacheFileStatDirectory() || !FdManager::DeleteCacheDirectory())){
@ -4555,13 +4555,10 @@ int main(int argc, char* argv[])
// set credential object
//
// This local variable is the only credential object.
// It is also set in the S3fsCurl class and this object is used.
//
S3fsCred s3fscredObj;
ps3fscred = &s3fscredObj;
if(!S3fsCurl::InitCredentialObject(&s3fscredObj)){
ps3fscred = new S3fsCred();
if(!S3fsCurl::InitCredentialObject(ps3fscred)){
S3FS_PRN_EXIT("Failed to setup credential object to s3fs curl.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4570,11 +4567,13 @@ int main(int argc, char* argv[])
case 0:
if(strcmp(long_opts[option_index].name, "version") == 0){
show_version();
delete ps3fscred;
exit(EXIT_SUCCESS);
}
break;
case 'h':
show_help();
delete ps3fscred;
exit(EXIT_SUCCESS);
case 'o':
break;
@ -4588,6 +4587,7 @@ int main(int argc, char* argv[])
case 'u': // --incomplete-mpu-list
if(NO_UTILITY_MODE != utility_mode){
S3FS_PRN_EXIT("already utility mode option is specified.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
utility_mode = INCOMP_TYPE_LIST;
@ -4595,6 +4595,7 @@ int main(int argc, char* argv[])
case 'a': // --incomplete-mpu-abort
if(NO_UTILITY_MODE != utility_mode){
S3FS_PRN_EXIT("already utility mode option is specified.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
utility_mode = INCOMP_TYPE_ABORT;
@ -4605,12 +4606,14 @@ int main(int argc, char* argv[])
}else if(NULL != optarg){
if(!convert_unixtime_from_option_arg(optarg, incomp_abort_time)){
S3FS_PRN_EXIT("--incomplete-mpu-abort option argument is wrong.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
// if optarg is null, incomp_abort_time is 24H(default)
break;
default:
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
@ -4620,12 +4623,14 @@ int main(int argc, char* argv[])
// Load SSE environment
if(!S3fsCurl::LoadEnvSse()){
S3FS_PRN_EXIT("something wrong about SSE environment.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
// ssl init
if(!s3fs_init_global_ssl()){
S3FS_PRN_EXIT("could not initialize for ssl libraries.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4633,6 +4638,7 @@ int main(int argc, char* argv[])
if(!init_parser_xml_lock()){
S3FS_PRN_EXIT("could not initialize mutex for xml parser.");
s3fs_destroy_global_ssl();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4665,6 +4671,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4680,6 +4687,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4697,6 +4705,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
if(!S3fsCurl::FinalCheckSse()){
@ -4705,6 +4714,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4725,6 +4735,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4740,6 +4751,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
@ -4751,6 +4763,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4761,6 +4774,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4792,7 +4806,11 @@ int main(int argc, char* argv[])
found = s3host.find("https:");
if(found != std::string::npos){
S3FS_PRN_EXIT("Using https and a bucket name with periods is unsupported.");
exit(1);
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
}
@ -4805,6 +4823,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(exitcode);
}
@ -4830,6 +4849,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
@ -4891,6 +4911,7 @@ int main(int argc, char* argv[])
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
destroy_basename_lock();
delete ps3fscred;
// cleanup xml2
xmlCleanupParser();

View File

@ -23,6 +23,7 @@
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <fstream>
#include <sstream>
@ -36,13 +37,85 @@
//-------------------------------------------------------------------
// Symbols
//-------------------------------------------------------------------
#define DEFAULT_AWS_PROFILE_NAME "default"
#define DEFAULT_AWS_PROFILE_NAME "default"
//-------------------------------------------------------------------
// External Credential dummy function
//-------------------------------------------------------------------
// [NOTE]
// This function expects the following values:
//
// detail=false ex. "Custom AWS Credential Library - v1.0.0"
// detail=true ex. "Custom AWS Credential Library - v1.0.0
// s3fs-fuse credential I/F library for S3 compatible strage X.
// Copyright(C) 2022 Foo"
//
const char* VersionS3fsCredential(bool detail)
{
static const char version[] = "built-in";
static const char detail_version[] =
"s3fs-fuse built-in Credential I/F Function\n"
"Copyright(C) 2007 s3fs-fuse\n";
S3FS_PRN_CRIT("Check why built-in function was called, the external credential library must have VersionS3fsCredential function.");
if(detail){
return detail_version;
}else{
return version;
}
}
bool InitS3fsCredential(const char* popts, char** pperrstr)
{
if(popts && 0 < strlen(popts)){
S3FS_PRN_WARN("The external credential library does not have InitS3fsCredential function, but credlib_opts value is not empty(%s)", popts);
}
if(pperrstr){
*pperrstr = strdup("The external credential library does not have InitS3fsCredential function, so built-in function was called.");
}else{
S3FS_PRN_INFO("The external credential library does not have InitS3fsCredential function, so built-in function was called.");
}
return true;
}
bool FreeS3fsCredential(char** pperrstr)
{
if(pperrstr){
*pperrstr = strdup("The external credential library does not have FreeS3fsCredential function, so built-in function was called.");
}else{
S3FS_PRN_INFO("The external credential library does not have FreeS3fsCredential function, so built-in function was called.");
}
return true;
}
bool UpdateS3fsCredential(char** ppaccess_key_id, char** ppserect_access_key, char** ppaccess_token, long long* ptoken_expire, char** pperrstr)
{
S3FS_PRN_INFO("Parameters : ppaccess_key_id=%p, ppserect_access_key=%p, ppaccess_token=%p, ptoken_expire=%p", ppaccess_key_id, ppserect_access_key, ppaccess_token, ptoken_expire);
if(pperrstr){
*pperrstr = strdup("Check why built-in function was called, the external credential library must have UpdateS3fsCredential function.");
}else{
S3FS_PRN_CRIT("Check why built-in function was called, the external credential library must have UpdateS3fsCredential function.");
}
if(ppaccess_key_id){
*ppaccess_key_id = NULL;
}
if(ppserect_access_key){
*ppserect_access_key = NULL;
}
if(ppaccess_token){
*ppaccess_token = NULL;
}
return false; // always false
}
//-------------------------------------------------------------------
// Class Variables
//-------------------------------------------------------------------
const char* S3fsCred::ALLBUCKET_FIELDS_TYPE = "";
const char* S3fsCred::KEYVAL_FIELDS_TYPE = "\t";
const char* S3fsCred::KEYVAL_FIELDS_TYPE = "\t";
const char* S3fsCred::AWS_ACCESSKEYID = "AWSAccessKeyId";
const char* S3fsCred::AWS_SECRETKEY = "AWSSecretKey";
@ -73,7 +146,7 @@ bool S3fsCred::SetBucket(const char* bucket)
const std::string& S3fsCred::GetBucket()
{
return S3fsCred::bucket_name;
return S3fsCred::bucket_name;
}
bool S3fsCred::ParseIAMRoleFromMetaDataResponse(const char* response, std::string& rolename)
@ -110,7 +183,13 @@ S3fsCred::S3fsCred() :
IAM_api_version(2),
IAM_field_count(4),
IAM_token_field("Token"),
IAM_expiry_field("Expiration")
IAM_expiry_field("Expiration"),
set_builtin_cred_opts(false),
hExtCredLib(NULL),
pFuncCredVersion(VersionS3fsCredential),
pFuncCredInit(InitS3fsCredential),
pFuncCredFree(FreeS3fsCredential),
pFuncCredUpdate(UpdateS3fsCredential)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
@ -127,6 +206,8 @@ S3fsCred::S3fsCred() :
S3fsCred::~S3fsCred()
{
UnloadExtCredLib();
if(is_lock_init){
int result;
if(0 != (result = pthread_mutex_destroy(&token_lock))){
@ -150,7 +231,7 @@ bool S3fsCred::SetS3fsPasswdFile(const char* file)
return true;
}
bool S3fsCred::IsSetPasswdFile()
bool S3fsCred::IsSetPasswdFile() const
{
return !passwd_file.empty();
}
@ -424,7 +505,7 @@ bool S3fsCred::LoadIAMCredentials(AutoLock::Type type)
S3FS_PRN_ERR("Something error occurred, could not set IAM role name.");
return false;
}
return true;
return true;
}
//
@ -551,7 +632,7 @@ bool S3fsCred::CheckS3fsPasswdFilePerms()
return false;
}
// Check readable
// Check readable
if(!IsReadableS3fsPasswdFile()){
S3FS_PRN_EXIT("S3fs passwd file \"%s\" is not readable.", passwd_file.c_str());
return false;
@ -1066,14 +1147,21 @@ bool S3fsCred::CheckIAMCredentialUpdate(std::string* access_key_id, std::string*
{
AutoLock auto_lock(&token_lock);
if(IsSetIAMRole(AutoLock::ALREADY_LOCKED) || is_ecs || is_ibm_iam_auth){
if(hExtCredLib || IsSetIAMRole(AutoLock::ALREADY_LOCKED) || is_ecs || is_ibm_iam_auth){
if(AWSAccessTokenExpire < (time(NULL) + S3fsCred::IAM_EXPIRE_MERGIN)){
S3FS_PRN_INFO("IAM Access Token refreshing...");
// update
if(!LoadIAMCredentials(AutoLock::ALREADY_LOCKED)){
S3FS_PRN_ERR("IAM Access Token refresh failed");
return false;
if(!hExtCredLib){
if(!LoadIAMCredentials(AutoLock::ALREADY_LOCKED)){
S3FS_PRN_ERR("Access Token refresh by built-in failed");
return false;
}
}else{
if(!UpdateExtCredentials(AutoLock::ALREADY_LOCKED)){
S3FS_PRN_ERR("Access Token refresh by %s(external credential library) failed", credlib.c_str());
return false;
}
}
S3FS_PRN_INFO("IAM Access Token refreshed");
}
@ -1097,6 +1185,217 @@ bool S3fsCred::CheckIAMCredentialUpdate(std::string* access_key_id, std::string*
return true;
}
const char* S3fsCred::GetCredFuncVersion(bool detail) const
{
static const char errVersion[] = "unknown";
if(!pFuncCredVersion){
return errVersion;
}
return (*pFuncCredVersion)(detail);
}
//-------------------------------------------------------------------
// Methods : External Credential Library
//-------------------------------------------------------------------
bool S3fsCred::SetExtCredLib(const char* arg)
{
if(!arg || strlen(arg) == 0){
return false;
}
credlib = arg;
return true;
}
bool S3fsCred::IsSetExtCredLib() const
{
return !credlib.empty();
}
bool S3fsCred::SetExtCredLibOpts(const char* args)
{
if(!args || strlen(args) == 0){
return false;
}
credlib_opts = args;
return true;
}
bool S3fsCred::IsSetExtCredLibOpts() const
{
return !credlib_opts.empty();
}
bool S3fsCred::InitExtCredLib()
{
if(!LoadExtCredLib()){
return false;
}
// Initialize library
if(!pFuncCredInit){
S3FS_PRN_CRIT("\"InitS3fsCredential\" function pointer is NULL, why?");
UnloadExtCredLib();
return false;
}
const char* popts = credlib_opts.empty() ? NULL : credlib_opts.c_str();
char* perrstr = NULL;
if(!(*pFuncCredInit)(popts, &perrstr)){
S3FS_PRN_ERR("Could not initialize %s(external credential library) by \"InitS3fsCredential\" function : %s", credlib.c_str(), perrstr ? perrstr : "unknown");
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(perrstr){
free(perrstr);
}
UnloadExtCredLib();
return false;
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(perrstr){
free(perrstr);
}
return true;
}
bool S3fsCred::LoadExtCredLib()
{
if(credlib.empty()){
return false;
}
UnloadExtCredLib();
S3FS_PRN_INFO("Load External Credential Library : %s", credlib.c_str());
// Open Library
//
// Search Library: (RPATH ->) LD_LIBRARY_PATH -> (RUNPATH ->) /etc/ld.so.cache -> /lib -> /usr/lib
//
if(NULL == (hExtCredLib = dlopen(credlib.c_str(), RTLD_LAZY))){
const char* preason = dlerror();
S3FS_PRN_ERR("Could not load %s(external credential library) by error : %s", credlib.c_str(), preason ? preason : "unknown");
return false;
}
// Set function pointers
if(NULL == (pFuncCredVersion = reinterpret_cast<fp_VersionS3fsCredential>(dlsym(hExtCredLib, "VersionS3fsCredential")))){
S3FS_PRN_ERR("%s(external credential library) does not have \"VersionS3fsCredential\" function which is required.", credlib.c_str());
UnloadExtCredLib();
return false;
}
if(NULL == (pFuncCredUpdate = reinterpret_cast<fp_UpdateS3fsCredential>(dlsym(hExtCredLib, "UpdateS3fsCredential")))){
S3FS_PRN_ERR("%s(external credential library) does not have \"UpdateS3fsCredential\" function which is required.", credlib.c_str());
UnloadExtCredLib();
return false;
}
if(NULL == (pFuncCredInit = reinterpret_cast<fp_InitS3fsCredential>(dlsym(hExtCredLib, "InitS3fsCredential")))){
S3FS_PRN_INFO("%s(external credential library) does not have \"InitS3fsCredential\" function which is optional.", credlib.c_str());
pFuncCredInit = InitS3fsCredential; // set built-in function
}
if(NULL == (pFuncCredFree = reinterpret_cast<fp_FreeS3fsCredential>(dlsym(hExtCredLib, "FreeS3fsCredential")))){
S3FS_PRN_INFO("%s(external credential library) does not have \"FreeS3fsCredential\" function which is optional.", credlib.c_str());
pFuncCredFree = FreeS3fsCredential; // set built-in function
}
S3FS_PRN_INFO("Succeed loading External Credential Library : %s", credlib.c_str());
return true;
}
bool S3fsCred::UnloadExtCredLib()
{
if(hExtCredLib){
S3FS_PRN_INFO("Unload External Credential Library : %s", credlib.c_str());
// Uninitialize library
if(!pFuncCredFree){
S3FS_PRN_CRIT("\"FreeS3fsCredential\" function pointer is NULL, why?");
}else{
char* perrstr = NULL;
if(!(*pFuncCredFree)(&perrstr)){
S3FS_PRN_ERR("Could not uninitialize by \"FreeS3fsCredential\" function : %s", perrstr ? perrstr : "unknown");
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(perrstr){
free(perrstr);
}
}
// reset
pFuncCredVersion = VersionS3fsCredential;
pFuncCredInit = InitS3fsCredential;
pFuncCredFree = FreeS3fsCredential;
pFuncCredUpdate = UpdateS3fsCredential;
// close
dlclose(hExtCredLib);
hExtCredLib = NULL;
}
return true;
}
bool S3fsCred::UpdateExtCredentials(AutoLock::Type type)
{
if(!hExtCredLib){
S3FS_PRN_CRIT("External Credential Library is not loaded, why?");
return false;
}
AutoLock auto_lock(&token_lock, type);
char* paccess_key_id = NULL;
char* pserect_access_key = NULL;
char* paccess_token = NULL;
char* perrstr = NULL;
long long token_expire = 0;
bool result = (*pFuncCredUpdate)(&paccess_key_id, &pserect_access_key, &paccess_token, &token_expire, &perrstr);
if(!result){
// error occurred
S3FS_PRN_ERR("Could not update credential by \"UpdateS3fsCredential\" function : %s", perrstr ? perrstr : "unknown");
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
}else if(!paccess_key_id || !pserect_access_key || !paccess_token || token_expire <= 0){
// some variables are wrong
S3FS_PRN_ERR("After updating credential by \"UpdateS3fsCredential\" function, but some variables are wrong : paccess_key_id=%p, pserect_access_key=%p, paccess_token=%p, token_expire=%lld", paccess_key_id, pserect_access_key, paccess_token, token_expire);
result = false;
}else{
// succeed updating
AWSAccessKeyId = paccess_key_id;
AWSSecretAccessKey = pserect_access_key;
AWSAccessToken = paccess_token;
AWSAccessTokenExpire = token_expire;
}
// clean
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(paccess_key_id){
free(paccess_key_id);
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(pserect_access_key){
free(pserect_access_key);
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(paccess_token){
free(paccess_token);
}
// cppcheck-suppress unmatchedSuppression
// cppcheck-suppress knownConditionTrueFalse
if(perrstr){
free(perrstr);
}
return result;
}
//-------------------------------------------------------------------
// Methods: Option detection
//-------------------------------------------------------------------
@ -1113,6 +1412,7 @@ int S3fsCred::DetectParam(const char* arg)
if(is_prefix(arg, "passwd_file=")){
SetS3fsPasswdFile(strchr(arg, '=') + sizeof(char));
set_builtin_cred_opts = true;
return 0;
}
@ -1123,11 +1423,13 @@ int S3fsCred::DetectParam(const char* arg)
SetIAMExpiryField("\"expiration\"");
SetIAMFieldCount(2);
SetIMDSVersion(1, AutoLock::NONE);
set_builtin_cred_opts = true;
return 0;
}
if(0 == strcmp(arg, "use_session_token")){
SetIsUseSessionToken(true);
set_builtin_cred_opts = true;
return 0;
}
@ -1142,11 +1444,13 @@ int S3fsCred::DetectParam(const char* arg)
}
endpoint_url = std::string(iam_endpoint) + "/identity/token";
SetIAMCredentialsURL(endpoint_url.c_str());
set_builtin_cred_opts = true;
return 0;
}
if(0 == strcmp(arg, "imdsv1only")){
SetIMDSVersion(1, AutoLock::NONE);
set_builtin_cred_opts = true;
return 0;
}
@ -1159,6 +1463,7 @@ int S3fsCred::DetectParam(const char* arg)
SetIMDSVersion(1, AutoLock::NONE);
SetIAMCredentialsURL("http://169.254.170.2");
SetIAMFieldCount(5);
set_builtin_cred_opts = true;
return 0;
}
@ -1171,18 +1476,37 @@ int S3fsCred::DetectParam(const char* arg)
// loading IAM role name in s3fs_init(), because we need to wait initializing curl.
//
SetIAMRoleMetadataType(true);
set_builtin_cred_opts = true;
return 0;
}else if(is_prefix(arg, "iam_role=")){
const char* role = strchr(arg, '=') + sizeof(char);
SetIAMRole(role, AutoLock::NONE);
SetIAMRoleMetadataType(false);
set_builtin_cred_opts = true;
return 0;
}
}
if(is_prefix(arg, "profile=")){
SetAwsProfileName(strchr(arg, '=') + sizeof(char));
set_builtin_cred_opts = true;
return 0;
}
if(is_prefix(arg, "credlib=")){
if(!SetExtCredLib(strchr(arg, '=') + sizeof(char))){
S3FS_PRN_EXIT("failed to set credlib option : %s", (strchr(arg, '=') + sizeof(char)));
return -1;
}
return 0;
}
if(is_prefix(arg, "credlib_opts=")){
if(!SetExtCredLibOpts(strchr(arg, '=') + sizeof(char))){
S3FS_PRN_EXIT("failed to set credlib_opts option : %s", (strchr(arg, '=') + sizeof(char)));
return -1;
}
return 0;
}
@ -1267,6 +1591,32 @@ bool S3fsCred::CheckAllParams()
return false;
}
}
// check External Credential Library
//
// [NOTE]
// If credlib(_opts) option (for External Credential Library) is specified,
// no other Credential related options can be specified. It is exclusive.
//
if(set_builtin_cred_opts && (IsSetExtCredLib() || IsSetExtCredLibOpts())){
S3FS_PRN_EXIT("The \"credlib\" or \"credlib_opts\" option and other credential-related options(passwd_file, iam_role, profile, use_session_token, ecs, imdsv1only, ibm_iam_auth, ibm_iam_endpoint, etc) cannot be specified together.");
return false;
}
// Load and Initialize external credential library
if(IsSetExtCredLib() || IsSetExtCredLibOpts()){
if(!IsSetExtCredLib()){
S3FS_PRN_EXIT("The \"credlib_opts\"(%s) is specifyed but \"credlib\" option is not specified.", credlib_opts.c_str());
return false;
}
if(!InitExtCredLib()){
S3FS_PRN_EXIT("failed to load the library specified by the option credlib(%s, %s).", credlib.c_str(), credlib_opts.c_str());
return false;
}
S3FS_PRN_INFO("Loaded External Credential Library:\n%s", GetCredFuncVersion(true));
}
return true;
}

View File

@ -22,6 +22,7 @@
#define S3FS_CRED_H_
#include "autolock.h"
#include "s3fs_extcred.h"
//----------------------------------------------
// Typedefs
@ -77,6 +78,16 @@ class S3fsCred
std::string IAM_expiry_field;
std::string IAM_role; // Protect exclusively
bool set_builtin_cred_opts; // true if options other than "credlib" is set
std::string credlib; // credlib(name or path)
std::string credlib_opts; // options for credlib
void* hExtCredLib;
fp_VersionS3fsCredential pFuncCredVersion;
fp_InitS3fsCredential pFuncCredInit;
fp_FreeS3fsCredential pFuncCredFree;
fp_UpdateS3fsCredential pFuncCredUpdate;
public:
static const char* IAMv2_token_url;
static int IAMv2_token_ttl;
@ -87,7 +98,7 @@ class S3fsCred
static bool ParseIAMRoleFromMetaDataResponse(const char* response, std::string& rolename);
bool SetS3fsPasswdFile(const char* file);
bool IsSetPasswdFile();
bool IsSetPasswdFile() const;
bool SetAwsProfileName(const char* profile_name);
bool SetIAMRoleMetadataType(bool flag);
@ -130,6 +141,16 @@ class S3fsCred
bool SetIAMCredentials(const char* response, AutoLock::Type type);
bool SetIAMRoleFromMetaData(const char* response, AutoLock::Type type);
bool SetExtCredLib(const char* arg);
bool IsSetExtCredLib() const;
bool SetExtCredLibOpts(const char* args);
bool IsSetExtCredLibOpts() const;
bool InitExtCredLib();
bool LoadExtCredLib();
bool UnloadExtCredLib();
bool UpdateExtCredentials(AutoLock::Type type);
static bool CheckForbiddenBucketParams();
public:
@ -144,6 +165,7 @@ class S3fsCred
bool LoadIAMRoleFromMetaData();
bool CheckIAMCredentialUpdate(std::string* access_key_id = NULL, std::string* secret_access_key = NULL, std::string* access_token = NULL);
const char* GetCredFuncVersion(bool detail) const;
int DetectParam(const char* arg);
bool CheckAllParams();

144
src/s3fs_extcred.h Normal file
View File

@ -0,0 +1,144 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_EXTCRED_H_
#define S3FS_EXTCRED_H_
//-------------------------------------------------------------------
// Attributes(weak) : use only in s3fs-fuse internally
//-------------------------------------------------------------------
// [NOTE]
// This macro is only used inside s3fs-fuse.
// External projects that utilize this header file substitute empty
//values as follows:
//
#ifndef S3FS_FUNCATTR_WEAK
#define S3FS_FUNCATTR_WEAK
#endif
extern "C" {
//-------------------------------------------------------------------
// Prototype for External Credential 4 functions
//-------------------------------------------------------------------
//
// [Required] VersionS3fsCredential
//
// Returns the library name and version as a string.
//
extern const char* VersionS3fsCredential(bool detail) S3FS_FUNCATTR_WEAK;
//
// [Optional] InitS3fsCredential
//
// A function that does the necessary initialization after the library is
// loaded. This function is called only once immediately after loading the
// library.
// If there is a required initialization inside the library, implement it.
// Implementation of this function is optional and not required. If not
// implemented, it will not be called.
//
// const char* popts : String passed with the credlib_opts option. If the
// credlib_opts option is not specified, NULL will be
// passed.
// char** pperrstr : pperrstr is used to pass the error message to the
// caller when an error occurs.
// If this pointer is not NULL, you can allocate memory
// and set an error message to it. The allocated memory
// area is freed by the caller.
//
extern bool InitS3fsCredential(const char* popts, char** pperrstr) S3FS_FUNCATTR_WEAK;
//
// [Optional] FreeS3fsCredential
//
// A function that is called only once just before the library is unloaded.
// If there is a required discard process in the library, implement it.
// Implementation of this feature is optional and not required.
// If not implemented, it will not be called.
//
// char** pperrstr : pperrstr is used to pass the error message to the
// caller when an error occurs.
// If this pointer is not NULL, you can allocate memory
// and set an error message to it. The allocated memory
// area is freed by the caller.
//
extern bool FreeS3fsCredential(char** pperrstr) S3FS_FUNCATTR_WEAK;
//
// [Required] UpdateS3fsCredential
//
// A function that updates the token.
//
// char** ppaccess_key_id : Allocate and set "Access Key ID" string
// area to *ppaccess_key_id.
// char** ppserect_access_key : Allocate and set "Access Secret Key ID"
// string area to *ppserect_access_key.
// char** ppaccess_token : Allocate and set "Token" string area to
// *ppaccess_token.
// long long* ptoken_expire : Set token expire time(time_t) value to
// *ptoken_expire.
// This is essentially a time_t* variable.
// To avoid system differences about time_t
// size, long long* is used.
// When setting the value, cast from time_t
// to long long to set the value.
// char** pperrstr : pperrstr is used to pass the error message to the
// caller when an error occurs.
//
// For all argument of the character string pointer(char **) set the
// allocated string area. The allocated area is freed by the caller.
//
extern bool UpdateS3fsCredential(char** ppaccess_key_id, char** ppserect_access_key, char** ppaccess_token, long long* ptoken_expire, char** pperrstr) S3FS_FUNCATTR_WEAK;
//---------------------------------------------------------
// Typedef Prototype function
//---------------------------------------------------------
//
// const char* VersionS3fsCredential()
//
typedef const char* (*fp_VersionS3fsCredential)(bool detail);
//
// bool InitS3fsCredential(char** pperrstr)
//
typedef bool (*fp_InitS3fsCredential)(const char* popts, char** pperrstr);
//
// bool FreeS3fsCredential(char** pperrstr)
//
typedef bool (*fp_FreeS3fsCredential)(char** pperrstr);
//
// bool UpdateS3fsCredential(char** ppaccess_key_id, char** ppserect_access_key, char** ppaccess_token, long long* ptoken_expire, char** pperrstr)
//
typedef bool (*fp_UpdateS3fsCredential)(char** ppaccess_key_id, char** ppserect_access_key, char** ppaccess_token, long long* ptoken_expire, char** pperrstr);
} // extern "C"
#endif // S3FS_EXTCRED_H_
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -341,6 +341,22 @@ static const char help_string[] =
" ibm_iam_endpoint (default is https://iam.cloud.ibm.com)\n"
" - sets the URL to use for IBM IAM authentication.\n"
"\n"
" credlib (default=\"\" which means disabled)\n"
" - Specifies the shared library that handles the credentials\n"
" containing the authentication token.\n"
" If this option is specified, the specified credential and token\n"
" processing provided by the shared library ant will be performed\n"
" instead of the built-in credential processing.\n"
" This option cannot be specified with passwd_file, profile,\n"
" use_session_token, ecs, ibm_iam_auth, ibm_iam_endpoint, imdsv1only\n"
" and iam_role option.\n"
"\n"
" credlib_opts (default=\"\" which means disabled)\n"
" - Specifies the options to pass when the shared library specified\n"
" in credlib is loaded and then initialized.\n"
" For the string specified in this option, specify the string defined\n"
" by the shared library.\n"
"\n"
" use_xattr (default is not handling the extended attribute)\n"
" Enable to handle the extended attribute (xattrs).\n"
" If you set this option, you can use the extended attribute.\n"