add session token support

This commit is contained in:
Michal Lula 2019-04-14 18:19:34 +02:00
parent 7095787f1f
commit f9cd43b684
5 changed files with 70 additions and 6 deletions

View File

@ -23,7 +23,7 @@ For unprivileged user.
s3fs is a FUSE filesystem that allows you to mount an Amazon S3 bucket as a local filesystem. It stores files natively and transparently in S3 (i.e., you can use other programs to access the same files).
.SH AUTHENTICATION
s3fs supports the standard AWS credentials (filehttps://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html) stored in `${HOME}/.aws/credentials`.
Alternatively, s3fs supports a custom passwd file.
Alternatively, s3fs supports a custom passwd file. Only AWS credentials file format can be used when AWS session token is required.
The s3fs password file has this format (use this format if you have only one set of credentials):
.RS 4
\fBaccessKeyId\fP:\fBsecretAccessKey\fP

View File

@ -384,6 +384,7 @@ int S3fsCurl::max_multireq = 20; // default
off_t S3fsCurl::multipart_size = MULTIPART_SIZE; // default
bool S3fsCurl::is_sigv4 = true; // default
bool S3fsCurl::is_ua = true; // default
bool S3fsCurl::is_use_session_token = false; // default
//-------------------------------------------------------------------
// Class methods for S3fsCurl
@ -1193,6 +1194,20 @@ bool S3fsCurl::SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey
return true;
}
bool S3fsCurl::SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char* SessionToken)
{
bool access_key_is_empty = !AccessKeyId || '\0' == AccessKeyId[0];
bool secret_access_key_is_empty = !SecretAccessKey || '\0' == SecretAccessKey[0];
bool session_token_is_empty = !SessionToken || '\0' == SessionToken[0];
if((!S3fsCurl::is_ibm_iam_auth && access_key_is_empty) || secret_access_key_is_empty || session_token_is_empty){
return false;
}
AWSAccessKeyId = AccessKeyId;
AWSSecretAccessKey = SecretAccessKey;
AWSAccessToken = SessionToken;
return true;
}
long S3fsCurl::SetSslVerifyHostname(long value)
{
if(0 != value && 1 != value){
@ -1210,6 +1225,13 @@ bool S3fsCurl::SetIsIBMIAMAuth(bool flag)
return old;
}
bool S3fsCurl::SetIsUseSessionToken(bool flag)
{
bool old = S3fsCurl::is_use_session_token;
S3fsCurl::is_use_session_token = flag;
return old;
}
bool S3fsCurl::SetIsECS(bool flag)
{
bool old = S3fsCurl::is_ecs;
@ -2407,7 +2429,7 @@ string S3fsCurl::CalcSignatureV2(const string& method, const string& strMD5, con
string Signature;
string StringToSign;
if(!S3fsCurl::IAM_role.empty() || S3fsCurl::is_ecs){
if(!S3fsCurl::IAM_role.empty() || S3fsCurl::is_ecs || S3fsCurl::is_use_session_token){
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-security-token", S3fsCurl::AWSAccessToken.c_str());
}
@ -2445,7 +2467,7 @@ string S3fsCurl::CalcSignature(const string& method, const string& canonical_uri
string Signature, StringCQ, StringToSign;
string uriencode;
if(!S3fsCurl::IAM_role.empty() || S3fsCurl::is_ecs){
if(!S3fsCurl::IAM_role.empty() || S3fsCurl::is_ecs || S3fsCurl::is_use_session_token){
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-security-token", S3fsCurl::AWSAccessToken.c_str());
}

View File

@ -270,6 +270,7 @@ class S3fsCurl
static std::string AWSAccessToken;
static time_t AWSAccessTokenExpire;
static bool is_ecs;
static bool is_use_session_token;
static bool is_ibm_iam_auth;
static std::string IAM_cred_url;
static size_t IAM_field_count;
@ -428,6 +429,7 @@ class S3fsCurl
static bool SetVerbose(bool flag);
static bool GetVerbose(void) { return S3fsCurl::is_verbose; }
static bool SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey);
static bool SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken);
static bool IsSetAccessKeyID(void){
return (0 < S3fsCurl::AWSAccessKeyId.size());
}
@ -443,6 +445,7 @@ class S3fsCurl
static int SetMaxMultiRequest(int max);
static int GetMaxMultiRequest(void) { return S3fsCurl::max_multireq; }
static bool SetIsECS(bool flag);
static bool SetIsUseSessionToken(bool flag);
static bool SetIsIBMIAMAuth(bool flag);
static size_t SetIAMFieldCount(size_t field_count);
static std::string SetIAMCredentialsURL(const char* url);

View File

@ -141,6 +141,7 @@ static bool is_remove_cache = false;
static bool is_ecs = false;
static bool is_ibm_iam_auth = false;
static bool is_use_xattr = false;
static bool is_use_session_token = false;
static bool create_bucket = false;
static int64_t singlepart_copy_limit = 512 * 1024 * 1024;
static bool is_specified_endpoint = false;
@ -4087,6 +4088,7 @@ static int read_aws_credentials_file(const std::string &filename)
string profile;
string accesskey;
string secret;
string session_token;
// read each line
string line;
@ -4106,6 +4108,7 @@ static int read_aws_credentials_file(const std::string &filename)
profile = line.substr(1, line.size() - 2);
accesskey.clear();
secret.clear();
session_token.clear();
}
size_t pos = line.find_first_of('=');
@ -4118,16 +4121,26 @@ static int read_aws_credentials_file(const std::string &filename)
accesskey = value;
}else if(key == "aws_secret_access_key"){
secret = value;
}else if(key == "aws_session_token"){
session_token = value;
}
}
if(profile != aws_profile){
return EXIT_FAILURE;
}
if(!S3fsCurl::SetAccessKey(accesskey.c_str(), secret.c_str())){
S3FS_PRN_EXIT("failed to set internal data for access key/secret key from aws credential file.");
return EXIT_FAILURE;
if (session_token.empty()) {
if(!S3fsCurl::SetAccessKey(accesskey.c_str(), secret.c_str())){
S3FS_PRN_EXIT("failed to set internal data for access key/secret key from aws credential file.");
return EXIT_FAILURE;
}
} else {
if (!S3fsCurl::SetAccessKeyWithSessionToken(accesskey.c_str(), secret.c_str(), session_token.c_str())) {
S3FS_PRN_EXIT("session token is invalid.");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
@ -4251,12 +4264,29 @@ static int get_access_keys()
// 3 - environment variables
char* AWSACCESSKEYID = getenv("AWSACCESSKEYID");
char* AWSSECRETACCESSKEY = getenv("AWSSECRETACCESSKEY");
char* AWSSESSIONTOKEN = getenv("AWSSESSIONTOKEN");
if(AWSACCESSKEYID != NULL || AWSSECRETACCESSKEY != NULL){
if( (AWSACCESSKEYID == NULL && AWSSECRETACCESSKEY != NULL) ||
(AWSACCESSKEYID != NULL && AWSSECRETACCESSKEY == NULL) ){
S3FS_PRN_EXIT("if environment variable AWSACCESSKEYID is set then AWSSECRETACCESSKEY must be set too.");
return EXIT_FAILURE;
}
S3FS_PRN_INFO2("access key from env variables");
if (AWSSESSIONTOKEN != NULL) {
S3FS_PRN_INFO2("session token is available");
is_use_session_token = true;
S3fsCurl::SetIsUseSessionToken(true);
if (!S3fsCurl::SetAccessKeyWithSessionToken(AWSACCESSKEYID, AWSSECRETACCESSKEY, AWSSESSIONTOKEN)) {
S3FS_PRN_EXIT("session token is invalid.");
return EXIT_FAILURE;
}
} else {
S3FS_PRN_INFO2("session token is not available");
if (is_use_session_token) {
S3FS_PRN_EXIT("environment variable AWSSESSIONTOKEN is expected to be set.");
return EXIT_FAILURE;
}
}
if(!S3fsCurl::SetAccessKey(AWSACCESSKEYID, AWSSECRETACCESSKEY)){
S3FS_PRN_EXIT("if one access key is specified, both keys need to be specified.");
return EXIT_FAILURE;
@ -4682,6 +4712,10 @@ static int my_fuse_opt_proc(void* data, const char* arg, int key, struct fuse_ar
is_ibm_iam_auth = true;
return 0;
}
if (0 == STR2NCMP(arg, "use_session_token")) {
S3fsCurl::SetIsUseSessionToken(true);
is_use_session_token = true;
}
if(0 == STR2NCMP(arg, "ibm_iam_endpoint=")){
std::string endpoint_url;
std::string iam_endpoint = strchr(arg, '=') + sizeof(char);

View File

@ -1329,6 +1329,11 @@ void show_help ()
" Unicode set.\n"
" Useful on clients not using utf-8 as their file system encoding.\n"
"\n"
" use_session_token - indicate that session token should be provided.\n"
" If credentials are provided by environment variables this switch\n"
" forces presence check of AWSSESSIONTOKEN variable.\n"
" Otherwise an error is returned."
"\n"
" dbglevel (default=\"crit\")\n"
" Set the debug message level. set value as crit (critical), err\n"
" (error), warn (warning), info (information) to debug level.\n"