mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2025-02-02 10:38:25 +00:00
Changed handling the credential in S3fsCred more robust
This commit is contained in:
parent
afb0897553
commit
684ced5a41
215
src/curl.cpp
215
src/curl.cpp
@ -2552,13 +2552,13 @@ int S3fsCurl::RequestPerform(bool dontAddAuthHeaders /*=false*/)
|
||||
// @param date e.g., get_date_rfc850()
|
||||
// @param resource e.g., "/pub"
|
||||
//
|
||||
std::string S3fsCurl::CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource)
|
||||
std::string S3fsCurl::CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource, const std::string& secret_access_key, const std::string& access_token)
|
||||
{
|
||||
std::string Signature;
|
||||
std::string StringToSign;
|
||||
|
||||
if(!S3fsCurl::ps3fscred->GetIAMRole().empty() || S3fsCurl::ps3fscred->IsECS() || S3fsCurl::ps3fscred->IsUseSessionToken()){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-security-token", S3fsCurl::ps3fscred->GetAccessToken().c_str());
|
||||
if(!access_token.empty()){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-security-token", access_token.c_str());
|
||||
}
|
||||
|
||||
StringToSign += method + "\n";
|
||||
@ -2568,8 +2568,8 @@ std::string S3fsCurl::CalcSignatureV2(const std::string& method, const std::stri
|
||||
StringToSign += get_canonical_headers(requestHeaders, true);
|
||||
StringToSign += resource;
|
||||
|
||||
const void* key = S3fsCurl::ps3fscred->GetSecretAccessKey().data();
|
||||
size_t key_len = S3fsCurl::ps3fscred->GetSecretAccessKey().size();
|
||||
const void* key = secret_access_key.data();
|
||||
size_t key_len = secret_access_key.size();
|
||||
const unsigned char* sdata = reinterpret_cast<const unsigned char*>(StringToSign.data());
|
||||
size_t sdata_len = StringToSign.size();
|
||||
unsigned char* md = NULL;
|
||||
@ -2590,13 +2590,13 @@ std::string S3fsCurl::CalcSignatureV2(const std::string& method, const std::stri
|
||||
return Signature;
|
||||
}
|
||||
|
||||
std::string S3fsCurl::CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601)
|
||||
std::string S3fsCurl::CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601, const std::string& secret_access_key, const std::string& access_token)
|
||||
{
|
||||
std::string Signature, StringCQ, StringToSign;
|
||||
std::string uriencode;
|
||||
|
||||
if(!S3fsCurl::ps3fscred->GetIAMRole().empty() || S3fsCurl::ps3fscred->IsECS() || S3fsCurl::ps3fscred->IsUseSessionToken()){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-security-token", S3fsCurl::ps3fscred->GetAccessToken().c_str());
|
||||
if(!access_token.empty()){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "x-amz-security-token", access_token.c_str());
|
||||
}
|
||||
|
||||
uriencode = urlEncode(canonical_uri);
|
||||
@ -2617,7 +2617,7 @@ std::string S3fsCurl::CalcSignature(const std::string& method, const std::string
|
||||
StringCQ += get_sorted_header_keys(requestHeaders) + "\n";
|
||||
StringCQ += payload_hash;
|
||||
|
||||
std::string kSecret = "AWS4" + S3fsCurl::ps3fscred->GetSecretAccessKey();
|
||||
std::string kSecret = "AWS4" + secret_access_key;
|
||||
unsigned char *kDate, *kRegion, *kService, *kSigning, *sRequest = NULL;
|
||||
unsigned int kDate_len,kRegion_len, kService_len, kSigning_len, sRequest_len = 0;
|
||||
|
||||
@ -2653,7 +2653,7 @@ std::string S3fsCurl::CalcSignature(const std::string& method, const std::string
|
||||
return Signature;
|
||||
}
|
||||
|
||||
void S3fsCurl::insertV4Headers()
|
||||
void S3fsCurl::insertV4Headers(const std::string& access_key_id, const std::string& secret_access_key, const std::string& access_token)
|
||||
{
|
||||
std::string server_path = type == REQTYPE_LISTBUCKET ? "/" : path;
|
||||
std::string payload_hash;
|
||||
@ -2711,13 +2711,13 @@ void S3fsCurl::insertV4Headers()
|
||||
}
|
||||
|
||||
if(!S3fsCurl::IsPublicBucket()){
|
||||
std::string Signature = CalcSignature(op, realpath, query_string + (type == REQTYPE_PREMULTIPOST || type == REQTYPE_MULTILIST ? "=" : ""), strdate, contentSHA256, date8601);
|
||||
std::string auth = "AWS4-HMAC-SHA256 Credential=" + S3fsCurl::ps3fscred->GetAccessKeyID() + "/" + strdate + "/" + endpoint + "/s3/aws4_request, SignedHeaders=" + get_sorted_header_keys(requestHeaders) + ", Signature=" + Signature;
|
||||
std::string Signature = CalcSignature(op, realpath, query_string + (type == REQTYPE_PREMULTIPOST || type == REQTYPE_MULTILIST ? "=" : ""), strdate, contentSHA256, date8601, secret_access_key, access_token);
|
||||
std::string auth = "AWS4-HMAC-SHA256 Credential=" + access_key_id + "/" + strdate + "/" + endpoint + "/s3/aws4_request, SignedHeaders=" + get_sorted_header_keys(requestHeaders) + ", Signature=" + Signature;
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Authorization", auth.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void S3fsCurl::insertV2Headers()
|
||||
void S3fsCurl::insertV2Headers(const std::string& access_key_id, const std::string& secret_access_key, const std::string& access_token)
|
||||
{
|
||||
std::string resource;
|
||||
std::string turl;
|
||||
@ -2734,34 +2734,39 @@ void S3fsCurl::insertV2Headers()
|
||||
}
|
||||
|
||||
if(!S3fsCurl::IsPublicBucket()){
|
||||
std::string Signature = CalcSignatureV2(op, get_header_value(requestHeaders, "Content-MD5"), get_header_value(requestHeaders, "Content-Type"), date, resource);
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Authorization", std::string("AWS " + S3fsCurl::ps3fscred->GetAccessKeyID() + ":" + Signature).c_str());
|
||||
std::string Signature = CalcSignatureV2(op, get_header_value(requestHeaders, "Content-MD5"), get_header_value(requestHeaders, "Content-Type"), date, resource, secret_access_key, access_token);
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Authorization", std::string("AWS " + access_key_id + ":" + Signature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void S3fsCurl::insertIBMIAMHeaders()
|
||||
void S3fsCurl::insertIBMIAMHeaders(const std::string& access_key_id, const std::string& access_token)
|
||||
{
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Authorization", ("Bearer " + S3fsCurl::ps3fscred->GetAccessToken()).c_str());
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Authorization", ("Bearer " + access_token).c_str());
|
||||
|
||||
if(op == "PUT" && path == mount_prefix + "/"){
|
||||
// ibm-service-instance-id header is required for bucket creation requests
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "ibm-service-instance-id", S3fsCurl::ps3fscred->GetAccessKeyID().c_str());
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "ibm-service-instance-id", access_key_id.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void S3fsCurl::insertAuthHeaders()
|
||||
{
|
||||
if(!S3fsCurl::ps3fscred->CheckIAMCredentialUpdate()){
|
||||
std::string access_key_id;
|
||||
std::string secret_access_key;
|
||||
std::string access_token;
|
||||
|
||||
// check and get credential variables
|
||||
if(!S3fsCurl::ps3fscred->CheckIAMCredentialUpdate(&access_key_id, &secret_access_key, &access_token)){
|
||||
S3FS_PRN_ERR("An error occurred in checking IAM credential.");
|
||||
return; // do not insert auth headers on error
|
||||
}
|
||||
|
||||
if(S3fsCurl::ps3fscred->IsIBMIAMAuth()){
|
||||
insertIBMIAMHeaders();
|
||||
insertIBMIAMHeaders(access_key_id, access_token);
|
||||
}else if(S3fsCurl::signature_type == V2_ONLY){
|
||||
insertV2Headers();
|
||||
insertV2Headers(access_key_id, secret_access_key, access_token);
|
||||
}else{
|
||||
insertV4Headers();
|
||||
insertV4Headers(access_key_id, secret_access_key, access_token);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2800,12 +2805,14 @@ int S3fsCurl::DeleteRequest(const char* tpath)
|
||||
return RequestPerform();
|
||||
}
|
||||
|
||||
//
|
||||
// Get the token that we need to pass along with AWS IMDSv2 API requests
|
||||
//
|
||||
int S3fsCurl::GetIAMv2ApiToken()
|
||||
int S3fsCurl::GetIAMv2ApiToken(const char* token_url, int token_ttl, const char* token_ttl_hdr, std::string& response)
|
||||
{
|
||||
url = std::string(S3fsCred::IAMv2_token_url);
|
||||
if(!token_url || !token_ttl_hdr){
|
||||
S3FS_PRN_ERR("IAMv2 token url(%s) or ttl_hdr(%s) parameter are wrong.", token_url ? token_url : "null", token_ttl_hdr ? token_ttl_hdr : "null");
|
||||
return -EIO;
|
||||
}
|
||||
response.erase();
|
||||
url = std::string(token_url);
|
||||
if(!CreateCurlHandle()){
|
||||
return -EIO;
|
||||
}
|
||||
@ -2813,8 +2820,8 @@ int S3fsCurl::GetIAMv2ApiToken()
|
||||
responseHeaders.clear();
|
||||
bodydata.Clear();
|
||||
|
||||
std::string ttlstr = str(S3fsCred::IAMv2_token_ttl);
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, S3fsCred::IAMv2_token_ttl_hdr, ttlstr.c_str());
|
||||
std::string ttlstr = str(token_ttl);
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, token_ttl_hdr, ttlstr.c_str());
|
||||
|
||||
// Curl appends an "Expect: 100-continue" header to the token request,
|
||||
// and aws responds with a 417 Expectation Failed. This ensures the
|
||||
@ -2837,16 +2844,18 @@ int S3fsCurl::GetIAMv2ApiToken()
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
// [NOTE]
|
||||
// Be sure to give "dontAddAuthHeaders=true".
|
||||
// If set to false(default), it will deadlock in S3fsCred.
|
||||
//
|
||||
int result = RequestPerform(true);
|
||||
|
||||
if(0 == result && !S3fsCurl::ps3fscred->SetIAMv2APIToken(bodydata.str())){
|
||||
S3FS_PRN_ERR("Error storing IMDSv2 API token.");
|
||||
result = -EIO;
|
||||
if(0 == result){
|
||||
response = bodydata.str();
|
||||
}else{
|
||||
S3FS_PRN_ERR("Error(%d) occurred, could not get IAMv2 api token.", result);
|
||||
}
|
||||
bodydata.Clear();
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_PUT, false)){
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2855,64 +2864,31 @@ int S3fsCurl::GetIAMv2ApiToken()
|
||||
// Get AccessKeyId/SecretAccessKey/AccessToken/Expiration by IAM role,
|
||||
// and Set these value to class variable.
|
||||
//
|
||||
int S3fsCurl::GetIAMCredentials()
|
||||
bool S3fsCurl::GetIAMCredentials(const char* cred_url, const char* iam_v2_token, const char* ibm_secret_access_key, std::string& response)
|
||||
{
|
||||
if (!S3fsCurl::ps3fscred->IsECS() && !S3fsCurl::ps3fscred->IsIBMIAMAuth()) {
|
||||
S3FS_PRN_INFO3("[IAM role=%s]", S3fsCurl::ps3fscred->GetIAMRole().c_str());
|
||||
|
||||
if(S3fsCurl::ps3fscred->GetIAMRole().empty()) {
|
||||
S3FS_PRN_ERR("IAM role name is empty.");
|
||||
return -EIO;
|
||||
}
|
||||
if(!cred_url){
|
||||
S3FS_PRN_ERR("url is null.");
|
||||
return false;
|
||||
}
|
||||
url = cred_url;
|
||||
response.erase();
|
||||
|
||||
// at first set type for handle
|
||||
type = REQTYPE_IAMCRED;
|
||||
|
||||
if(!CreateCurlHandle()){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
|
||||
// url
|
||||
if(S3fsCurl::ps3fscred->IsECS()){
|
||||
const char *env = std::getenv(S3fsCred::ECS_IAM_ENV_VAR);
|
||||
if(env == NULL){
|
||||
S3FS_PRN_ERR("%s is not set.", S3fsCred::ECS_IAM_ENV_VAR);
|
||||
return -EIO;
|
||||
}
|
||||
url = S3fsCurl::ps3fscred->GetIAMCredentialsURL() + env;
|
||||
}else{
|
||||
if(S3fsCurl::ps3fscred->GetIMDSVersion() > 1){
|
||||
int result = GetIAMv2ApiToken();
|
||||
if(-ENOENT == result){
|
||||
// If we get a 404 back when requesting the token service,
|
||||
// then it's highly likely we're running in an environment
|
||||
// that doesn't support the AWS IMDSv2 API, so we'll skip
|
||||
// the token retrieval in the future.
|
||||
S3fsCurl::ps3fscred->SetIMDSVersion(1);
|
||||
}else if(result != 0){
|
||||
// If we get an unexpected error when retrieving the API
|
||||
// token, log it but continue. Requirement for including
|
||||
// an API token with the metadata request may or may not
|
||||
// be required, so we should not abort here.
|
||||
S3FS_PRN_ERR("AWS IMDSv2 token retrieval failed: %d", result);
|
||||
}
|
||||
}
|
||||
url = S3fsCurl::ps3fscred->GetIAMCredentialsURL() + S3fsCurl::ps3fscred->GetIAMRole();
|
||||
}
|
||||
|
||||
requestHeaders = NULL;
|
||||
responseHeaders.clear();
|
||||
bodydata.Clear();
|
||||
std::string postContent;
|
||||
|
||||
if(S3fsCurl::ps3fscred->IsIBMIAMAuth()){
|
||||
url = S3fsCurl::ps3fscred->GetIAMCredentialsURL();
|
||||
|
||||
if(ibm_secret_access_key){
|
||||
// make contents
|
||||
postContent += "grant_type=urn:ibm:params:oauth:grant-type:apikey";
|
||||
postContent += "&response_type=cloud_iam";
|
||||
postContent += "&apikey=" + S3fsCurl::ps3fscred->GetSecretAccessKey();
|
||||
postContent += "&apikey=" + std::string(ibm_secret_access_key);
|
||||
|
||||
// set postdata
|
||||
postdata = reinterpret_cast<const unsigned char*>(postContent.c_str());
|
||||
@ -2923,53 +2899,65 @@ int S3fsCurl::GetIAMCredentials()
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, "Authorization", "Basic Yng6Yng=");
|
||||
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_POST, true)){ // POST
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_POSTFIELDSIZE, static_cast<curl_off_t>(postdata_remaining))){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_READDATA, (void*)this)){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_READFUNCTION, S3fsCurl::ReadCallback)){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(S3fsCurl::ps3fscred->GetIMDSVersion() > 1){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, S3fsCred::IAMv2_token_hdr, S3fsCurl::ps3fscred->GetIAMv2APIToken().c_str());
|
||||
if(iam_v2_token){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, S3fsCred::IAMv2_token_hdr, iam_v2_token);
|
||||
}
|
||||
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_URL, url.c_str())){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_WRITEDATA, (void*)&bodydata)){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback)){
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
if(!S3fsCurl::AddUserAgent(hCurl)){ // put User-Agent
|
||||
return -EIO;
|
||||
return false;
|
||||
}
|
||||
|
||||
// [NOTE]
|
||||
// Be sure to give "dontAddAuthHeaders=true".
|
||||
// If set to false(default), it will deadlock in S3fsCred.
|
||||
//
|
||||
int result = RequestPerform(true);
|
||||
|
||||
// analyzing response
|
||||
if(0 == result && !S3fsCurl::ps3fscred->SetIAMCredentials(bodydata.str())){
|
||||
S3FS_PRN_ERR("Something error occurred, could not get IAM credential.");
|
||||
result = -EIO;
|
||||
if(0 == result){
|
||||
response = bodydata.str();
|
||||
}else{
|
||||
S3FS_PRN_ERR("Error(%d) occurred, could not get IAM role name.", result);
|
||||
}
|
||||
bodydata.Clear();
|
||||
|
||||
return result;
|
||||
return (0 == result);
|
||||
}
|
||||
|
||||
//
|
||||
// Get IAM role name automatically.
|
||||
//
|
||||
bool S3fsCurl::LoadIAMRoleFromMetaData()
|
||||
bool S3fsCurl::GetIAMRoleFromMetaData(const char* cred_url, const char* iam_v2_token, std::string& token)
|
||||
{
|
||||
if(!cred_url){
|
||||
S3FS_PRN_ERR("url is null.");
|
||||
return false;
|
||||
}
|
||||
url = cred_url;
|
||||
token.erase();
|
||||
|
||||
S3FS_PRN_INFO3("Get IAM Role name");
|
||||
|
||||
// at first set type for handle
|
||||
@ -2978,40 +2966,12 @@ bool S3fsCurl::LoadIAMRoleFromMetaData()
|
||||
if(!CreateCurlHandle()){
|
||||
return false;
|
||||
}
|
||||
|
||||
// url
|
||||
if(S3fsCurl::ps3fscred->IsECS()){
|
||||
const char *env = std::getenv(S3fsCred::ECS_IAM_ENV_VAR);
|
||||
if(env == NULL){
|
||||
S3FS_PRN_ERR("%s is not set.", S3fsCred::ECS_IAM_ENV_VAR);
|
||||
return -EIO;
|
||||
}
|
||||
url = S3fsCurl::ps3fscred->GetIAMCredentialsURL() + env;
|
||||
}else{
|
||||
if(S3fsCurl::ps3fscred->GetIMDSVersion() > 1){
|
||||
int result = GetIAMv2ApiToken();
|
||||
if(-ENOENT == result){
|
||||
// If we get a 404 back when requesting the token service,
|
||||
// then it's highly likely we're running in an environment
|
||||
// that doesn't support the AWS IMDSv2 API, so we'll skip
|
||||
// the token retrieval in the future.
|
||||
S3fsCurl::ps3fscred->SetIMDSVersion(1);
|
||||
}else if(result != 0){
|
||||
// If we get an unexpected error when retrieving the API
|
||||
// token, log it but continue. Requirement for including
|
||||
// an API token with the metadata request may or may not
|
||||
// be enforced, so we should not abort here.
|
||||
S3FS_PRN_ERR("AWS IMDSv2 token retrieval failed: %d", result);
|
||||
}
|
||||
}
|
||||
url = S3fsCurl::ps3fscred->GetIAMCredentialsURL();
|
||||
}
|
||||
requestHeaders = NULL;
|
||||
responseHeaders.clear();
|
||||
bodydata.Clear();
|
||||
|
||||
if(S3fsCurl::ps3fscred->GetIMDSVersion() > 1){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, S3fsCred::IAMv2_token_hdr, S3fsCurl::ps3fscred->GetIAMv2APIToken().c_str());
|
||||
if(iam_v2_token){
|
||||
requestHeaders = curl_slist_sort_insert(requestHeaders, S3fsCred::IAMv2_token_hdr, iam_v2_token);
|
||||
}
|
||||
|
||||
if(CURLE_OK != curl_easy_setopt(hCurl, CURLOPT_URL, url.c_str())){
|
||||
@ -3027,12 +2987,17 @@ bool S3fsCurl::LoadIAMRoleFromMetaData()
|
||||
return false;
|
||||
}
|
||||
|
||||
// [NOTE]
|
||||
// Be sure to give "dontAddAuthHeaders=true".
|
||||
// If set to false(default), it will deadlock in S3fsCred.
|
||||
//
|
||||
int result = RequestPerform(true);
|
||||
|
||||
// analyzing response
|
||||
if(0 == result && !S3fsCurl::ps3fscred->SetIAMRoleFromMetaData(bodydata.str())){
|
||||
S3FS_PRN_ERR("Something error occurred, could not get IAM role name.");
|
||||
result = -EIO;
|
||||
if(0 == result){
|
||||
token = bodydata.str();
|
||||
}else{
|
||||
S3FS_PRN_ERR("Error(%d) occurred, could not get IAM role name from meta data.", result);
|
||||
}
|
||||
bodydata.Clear();
|
||||
|
||||
|
16
src/curl.h
16
src/curl.h
@ -249,13 +249,12 @@ class S3fsCurl
|
||||
bool ResetHandle(bool lock_already_held = false);
|
||||
bool RemakeHandle();
|
||||
bool ClearInternalData();
|
||||
void insertV4Headers();
|
||||
void insertV2Headers();
|
||||
void insertIBMIAMHeaders();
|
||||
void insertV4Headers(const std::string& access_key_id, const std::string& secret_access_key, const std::string& access_token);
|
||||
void insertV2Headers(const std::string& access_key_id, const std::string& secret_access_key, const std::string& access_token);
|
||||
void insertIBMIAMHeaders(const std::string& access_key_id, const std::string& access_token);
|
||||
void insertAuthHeaders();
|
||||
std::string CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource);
|
||||
std::string CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601);
|
||||
int GetIAMv2ApiToken();
|
||||
std::string CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource, const std::string& secret_access_key, const std::string& access_token);
|
||||
std::string CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601, const std::string& secret_access_key, const std::string& access_token);
|
||||
int UploadMultipartPostSetup(const char* tpath, int part_num, const std::string& upload_id);
|
||||
int CopyMultipartPostSetup(const char* from, const char* to, int part_num, const std::string& upload_id, headers_t& meta);
|
||||
bool UploadMultipartPostComplete();
|
||||
@ -337,12 +336,13 @@ class S3fsCurl
|
||||
bool CreateCurlHandle(bool only_pool = false, bool remake = false);
|
||||
bool DestroyCurlHandle(bool restore_pool = true, bool clear_internal_data = true);
|
||||
|
||||
int GetIAMCredentials();
|
||||
bool LoadIAMRoleFromMetaData();
|
||||
bool GetIAMCredentials(const char* cred_url, const char* iam_v2_token, const char* ibm_secret_access_key, std::string& response);
|
||||
bool GetIAMRoleFromMetaData(const char* cred_url, const char* iam_v2_token, std::string& token);
|
||||
bool AddSseRequestHead(sse_type_t ssetype, const std::string& ssevalue, bool is_only_c, bool is_copy);
|
||||
bool GetResponseCode(long& responseCode, bool from_curl_handle = true);
|
||||
int RequestPerform(bool dontAddAuthHeaders=false);
|
||||
int DeleteRequest(const char* tpath);
|
||||
int GetIAMv2ApiToken(const char* token_url, int token_ttl, const char* token_ttl_hdr, std::string& response);
|
||||
bool PreHeadRequest(const char* tpath, const char* bpath = NULL, const char* savedpath = NULL, size_t ssekey_pos = -1);
|
||||
bool PreHeadRequest(const std::string& tpath, const std::string& bpath, const std::string& savedpath, size_t ssekey_pos = -1) {
|
||||
return PreHeadRequest(tpath.c_str(), bpath.c_str(), savedpath.c_str(), ssekey_pos);
|
||||
|
16
src/s3fs.cpp
16
src/s3fs.cpp
@ -3380,16 +3380,10 @@ static void* s3fs_init(struct fuse_conn_info* conn)
|
||||
}
|
||||
|
||||
// check loading IAM role name
|
||||
if(ps3fscred->IsIAMRoleMetadataType()){
|
||||
// load IAM role name from http://169.254.169.254/latest/meta-data/iam/security-credentials
|
||||
//
|
||||
S3fsCurl s3fscurl;
|
||||
if(!s3fscurl.LoadIAMRoleFromMetaData()){
|
||||
S3FS_PRN_CRIT("could not load IAM role name from meta data.");
|
||||
s3fs_exit_fuseloop(EXIT_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
S3FS_PRN_INFO("loaded IAM role name = %s", ps3fscred->GetIAMRole().c_str());
|
||||
if(!ps3fscred->LoadIAMRoleFromMetaData()){
|
||||
S3FS_PRN_CRIT("could not load IAM role name from meta data.");
|
||||
s3fs_exit_fuseloop(EXIT_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check Bucket
|
||||
@ -3502,7 +3496,7 @@ static int s3fs_check_service()
|
||||
|
||||
// At first time for access S3, we check IAM role if it sets.
|
||||
if(!ps3fscred->CheckIAMCredentialUpdate()){
|
||||
S3FS_PRN_CRIT("Failed to check IAM role name(%s).", ps3fscred->GetIAMRole().c_str());
|
||||
S3FS_PRN_CRIT("Failed to initialize IAM credential.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,7 @@ bool S3fsCred::ParseIAMRoleFromMetaDataResponse(const char* response, std::strin
|
||||
// Methods : Constructor / Destructor
|
||||
//-------------------------------------------------------------------
|
||||
S3fsCred::S3fsCred() :
|
||||
is_lock_init(false),
|
||||
passwd_file(""),
|
||||
aws_profile(DEFAULT_AWS_PROFILE_NAME),
|
||||
load_iamrole(false),
|
||||
@ -115,10 +116,29 @@ S3fsCred::S3fsCred() :
|
||||
IAM_expiry_field("Expiration"),
|
||||
IAM_role("")
|
||||
{
|
||||
pthread_mutexattr_t attr;
|
||||
pthread_mutexattr_init(&attr);
|
||||
#if S3FS_PTHREAD_ERRORCHECK
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
#endif
|
||||
int result;
|
||||
if(0 != (result = pthread_mutex_init(&token_lock, &attr))){
|
||||
S3FS_PRN_CRIT("failed to init token_lock: %d", result);
|
||||
abort();
|
||||
}
|
||||
is_lock_init = true;
|
||||
}
|
||||
|
||||
S3fsCred::~S3fsCred()
|
||||
{
|
||||
if(is_lock_init){
|
||||
int result;
|
||||
if(0 != (result = pthread_mutex_destroy(&token_lock))){
|
||||
S3FS_PRN_CRIT("failed to destroy token_lock: %d", result);
|
||||
abort();
|
||||
}
|
||||
is_lock_init = false;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@ -156,8 +176,10 @@ bool S3fsCred::SetIAMRoleMetadataType(bool flag)
|
||||
return old;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey)
|
||||
bool S3fsCred::SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey, AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
if((!is_ibm_iam_auth && (!AccessKeyId || '\0' == AccessKeyId[0])) || !SecretAccessKey || '\0' == SecretAccessKey[0]){
|
||||
return false;
|
||||
}
|
||||
@ -167,8 +189,10 @@ bool S3fsCred::SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken)
|
||||
bool S3fsCred::SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken, AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
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];
|
||||
@ -184,9 +208,11 @@ bool S3fsCred::SetAccessKeyWithSessionToken(const char* AccessKeyId, const char*
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCred::IsSetAccessKeys() const
|
||||
bool S3fsCred::IsSetAccessKeys(AutoLock::Type type)
|
||||
{
|
||||
return !IAM_role.empty() || ((!AWSAccessKeyId.empty() || is_ibm_iam_auth) && !AWSSecretAccessKey.empty());
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
return IsSetIAMRole(AutoLock::ALREADY_LOCKED) || ((!AWSAccessKeyId.empty() || is_ibm_iam_auth) && !AWSSecretAccessKey.empty());
|
||||
}
|
||||
|
||||
bool S3fsCred::SetIsECS(bool flag)
|
||||
@ -210,11 +236,26 @@ bool S3fsCred::SetIsIBMIAMAuth(bool flag)
|
||||
return old;
|
||||
}
|
||||
|
||||
std::string S3fsCred::SetIAMRole(const char* role)
|
||||
bool S3fsCred::SetIAMRole(const char* role, AutoLock::Type type)
|
||||
{
|
||||
std::string old = IAM_role;
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
IAM_role = role ? role : "";
|
||||
return old;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string S3fsCred::GetIAMRole(AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
return IAM_role;
|
||||
}
|
||||
|
||||
bool S3fsCred::IsSetIAMRole(AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
return !IAM_role.empty();
|
||||
}
|
||||
|
||||
size_t S3fsCred::SetIAMFieldCount(size_t field_count)
|
||||
@ -245,24 +286,189 @@ std::string S3fsCred::SetIAMExpiryField(const char* expiry_field)
|
||||
return old;
|
||||
}
|
||||
|
||||
int S3fsCred::SetIMDSVersion(int version)
|
||||
bool S3fsCred::GetIAMCredentialsURL(std::string& url, bool check_iam_role, AutoLock::Type type)
|
||||
{
|
||||
// check
|
||||
if(check_iam_role && !is_ecs && !IsIBMIAMAuth()){
|
||||
if(!IsSetIAMRole(type)) {
|
||||
S3FS_PRN_ERR("IAM role name is empty.");
|
||||
return false;
|
||||
}
|
||||
S3FS_PRN_INFO3("[IAM role=%s]", GetIAMRole(type).c_str());
|
||||
}
|
||||
|
||||
if(is_ecs){
|
||||
const char *env = std::getenv(S3fsCred::ECS_IAM_ENV_VAR);
|
||||
if(env == NULL){
|
||||
S3FS_PRN_ERR("%s is not set.", S3fsCred::ECS_IAM_ENV_VAR);
|
||||
return false;
|
||||
}
|
||||
url = IAM_cred_url + env;
|
||||
|
||||
}else if(IsIBMIAMAuth()){
|
||||
url = IAM_cred_url;
|
||||
|
||||
}else{
|
||||
// [NOTE]
|
||||
// To avoid deadlocking, do not manipulate the S3fsCred object
|
||||
// in the S3fsCurl::GetIAMv2ApiToken method (when retrying).
|
||||
//
|
||||
AutoLock auto_lock(&token_lock, type); // Lock for IAM_api_version, IAMv2_api_token
|
||||
|
||||
if(GetIMDSVersion(AutoLock::ALREADY_LOCKED) > 1){
|
||||
S3fsCurl s3fscurl;
|
||||
std::string token;
|
||||
int result = s3fscurl.GetIAMv2ApiToken(S3fsCred::IAMv2_token_url, S3fsCred::IAMv2_token_ttl, S3fsCred::IAMv2_token_ttl_hdr, token);
|
||||
if(-ENOENT == result){
|
||||
// If we get a 404 back when requesting the token service,
|
||||
// then it's highly likely we're running in an environment
|
||||
// that doesn't support the AWS IMDSv2 API, so we'll skip
|
||||
// the token retrieval in the future.
|
||||
SetIMDSVersion(1, AutoLock::ALREADY_LOCKED);
|
||||
|
||||
}else if(result != 0){
|
||||
// If we get an unexpected error when retrieving the API
|
||||
// token, log it but continue. Requirement for including
|
||||
// an API token with the metadata request may or may not
|
||||
// be required, so we should not abort here.
|
||||
S3FS_PRN_ERR("AWS IMDSv2 token retrieval failed: %d", result);
|
||||
|
||||
}else{
|
||||
// Set token
|
||||
if(!SetIAMv2APIToken(token, AutoLock::ALREADY_LOCKED)){
|
||||
S3FS_PRN_ERR("Error storing IMDSv2 API token(%s).", token.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
if(check_iam_role){
|
||||
url = IAM_cred_url + GetIAMRole(AutoLock::ALREADY_LOCKED);
|
||||
}else{
|
||||
url = IAM_cred_url;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int S3fsCred::SetIMDSVersion(int version, AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
int old = IAM_api_version;
|
||||
IAM_api_version = version;
|
||||
return old;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetIAMv2APIToken(const char* response)
|
||||
int S3fsCred::GetIMDSVersion(AutoLock::Type type)
|
||||
{
|
||||
S3FS_PRN_INFO3("Setting AWS IMDSv2 API token to %s", response ? response : "(null)");
|
||||
if(!response){
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
return IAM_api_version;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetIAMv2APIToken(const std::string& token, AutoLock::Type type)
|
||||
{
|
||||
S3FS_PRN_INFO3("Setting AWS IMDSv2 API token to %s", token.c_str());
|
||||
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
if(token.empty()){
|
||||
return false;
|
||||
}
|
||||
IAMv2_api_token = std::string(response);
|
||||
IAMv2_api_token = token;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetIAMCredentials(const char* response)
|
||||
std::string S3fsCred::GetIAMv2APIToken(AutoLock::Type type)
|
||||
{
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
return IAMv2_api_token;
|
||||
}
|
||||
|
||||
// [NOTE]
|
||||
// Currently, token_lock is always locked before calling this method,
|
||||
// and this method calls the S3fsCurl::GetIAMCredentials method.
|
||||
// Currently, when the request fails and retries in the process of
|
||||
// S3fsCurl::GetIAMCredentials, does not use the S3fsCred object in
|
||||
// retry logic.
|
||||
// Be careful not to deadlock whenever you change this logic.
|
||||
//
|
||||
bool S3fsCred::LoadIAMCredentials(AutoLock::Type type)
|
||||
{
|
||||
// url(check iam role)
|
||||
std::string url;
|
||||
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
if(!GetIAMCredentialsURL(url, true, AutoLock::ALREADY_LOCKED)){
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* iam_v2_token = NULL;
|
||||
std::string str_iam_v2_token;
|
||||
if(GetIMDSVersion(AutoLock::ALREADY_LOCKED) > 1){
|
||||
str_iam_v2_token = GetIAMv2APIToken(AutoLock::ALREADY_LOCKED);
|
||||
iam_v2_token = str_iam_v2_token.c_str();
|
||||
}
|
||||
|
||||
const char* ibm_secret_access_key = NULL;
|
||||
std::string str_ibm_secret_access_key;
|
||||
if(IsIBMIAMAuth()){
|
||||
str_ibm_secret_access_key = AWSSecretAccessKey;
|
||||
ibm_secret_access_key = str_ibm_secret_access_key.c_str();
|
||||
}
|
||||
|
||||
S3fsCurl s3fscurl;
|
||||
std::string response;
|
||||
if(!s3fscurl.GetIAMCredentials(url.c_str(), iam_v2_token, ibm_secret_access_key, response)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!SetIAMCredentials(response.c_str(), AutoLock::ALREADY_LOCKED)){
|
||||
S3FS_PRN_ERR("Something error occurred, could not set IAM role name.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// load IAM role name from http://169.254.169.254/latest/meta-data/iam/security-credentials
|
||||
//
|
||||
bool S3fsCred::LoadIAMRoleFromMetaData()
|
||||
{
|
||||
AutoLock auto_lock(&token_lock);
|
||||
|
||||
if(load_iamrole){
|
||||
// url(not check iam role)
|
||||
std::string url;
|
||||
|
||||
if(!GetIAMCredentialsURL(url, false, AutoLock::ALREADY_LOCKED)){
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* iam_v2_token = NULL;
|
||||
std::string str_iam_v2_token;
|
||||
if(GetIMDSVersion(AutoLock::ALREADY_LOCKED) > 1){
|
||||
str_iam_v2_token = GetIAMv2APIToken(AutoLock::ALREADY_LOCKED);
|
||||
iam_v2_token = str_iam_v2_token.c_str();
|
||||
}
|
||||
|
||||
S3fsCurl s3fscurl;
|
||||
std::string token;
|
||||
if(!s3fscurl.GetIAMRoleFromMetaData(url.c_str(), iam_v2_token, token)){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!SetIAMRoleFromMetaData(token.c_str(), AutoLock::ALREADY_LOCKED)){
|
||||
S3FS_PRN_ERR("Something error occurred, could not set IAM role name.");
|
||||
return false;
|
||||
}
|
||||
S3FS_PRN_INFO("loaded IAM role name = %s", GetIAMRole(AutoLock::ALREADY_LOCKED).c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetIAMCredentials(const char* response, AutoLock::Type type)
|
||||
{
|
||||
S3FS_PRN_INFO3("IAM credential response = \"%s\"", response);
|
||||
|
||||
@ -276,6 +482,8 @@ bool S3fsCred::SetIAMCredentials(const char* response)
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoLock auto_lock(&token_lock, type);
|
||||
|
||||
AWSAccessToken = keyval[IAM_token_field];
|
||||
|
||||
if(is_ibm_iam_auth){
|
||||
@ -292,7 +500,7 @@ bool S3fsCred::SetIAMCredentials(const char* response)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCred::SetIAMRoleFromMetaData(const char* response)
|
||||
bool S3fsCred::SetIAMRoleFromMetaData(const char* response, AutoLock::Type type)
|
||||
{
|
||||
S3FS_PRN_INFO3("IAM role name response = \"%s\"", response ? response : "(null)");
|
||||
|
||||
@ -301,11 +509,10 @@ bool S3fsCred::SetIAMRoleFromMetaData(const char* response)
|
||||
return false;
|
||||
}
|
||||
|
||||
SetIAMRole(rolename.c_str());
|
||||
SetIAMRole(rolename.c_str(), type);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Methods : for Credentials
|
||||
//-------------------------------------------------------------------
|
||||
@ -504,7 +711,7 @@ bool S3fsCred::ParseS3fsPasswdFile(bucketkvmap_t& resmap)
|
||||
//
|
||||
// only one default key pair is allowed, but not required
|
||||
//
|
||||
bool S3fsCred::ReadS3fsPasswdFile()
|
||||
bool S3fsCred::ReadS3fsPasswdFile(AutoLock::Type type)
|
||||
{
|
||||
bucketkvmap_t bucketmap;
|
||||
kvmap_t keyval;
|
||||
@ -529,11 +736,17 @@ bool S3fsCred::ReadS3fsPasswdFile()
|
||||
bucketkvmap_t::iterator it = bucketmap.find(S3fsCred::KEYVAL_FIELDS_TYPE);
|
||||
if(bucketmap.end() != it){
|
||||
// aws format
|
||||
int result = CheckS3fsCredentialAwsFormat(it->second);
|
||||
std::string access_key_id;
|
||||
std::string secret_access_key;
|
||||
int result = CheckS3fsCredentialAwsFormat(it->second, access_key_id, secret_access_key);
|
||||
if(-1 == result){
|
||||
return false;
|
||||
}else if(1 == result){
|
||||
// success to set
|
||||
// found ascess(secret) keys
|
||||
if(!SetAccessKey(access_key_id.c_str(), secret_access_key.c_str(), type)){
|
||||
S3FS_PRN_EXIT("failed to set access key/secret key.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -556,7 +769,7 @@ bool S3fsCred::ReadS3fsPasswdFile()
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!SetAccessKey(aws_accesskeyid_it->second.c_str(), aws_secretkey_it->second.c_str())){
|
||||
if(!SetAccessKey(aws_accesskeyid_it->second.c_str(), aws_secretkey_it->second.c_str(), type)){
|
||||
S3FS_PRN_EXIT("failed to set internal data for access key/secret key from passwd file.");
|
||||
return false;
|
||||
}
|
||||
@ -568,7 +781,7 @@ bool S3fsCred::ReadS3fsPasswdFile()
|
||||
// 0 - NG(could not read)
|
||||
// -1 - Should shutdown immediately
|
||||
//
|
||||
int S3fsCred::CheckS3fsCredentialAwsFormat(const kvmap_t& kvmap)
|
||||
int S3fsCred::CheckS3fsCredentialAwsFormat(const kvmap_t& kvmap, std::string& access_key_id, std::string& secret_access_key)
|
||||
{
|
||||
std::string str1(S3fsCred::AWS_ACCESSKEYID);
|
||||
std::string str2(S3fsCred::AWS_SECRETKEY);
|
||||
@ -585,17 +798,16 @@ int S3fsCred::CheckS3fsCredentialAwsFormat(const kvmap_t& kvmap)
|
||||
S3FS_PRN_EXIT("AWSAccesskey or AWSSecretkey is not specified.");
|
||||
return -1;
|
||||
}
|
||||
if(!SetAccessKey(str1_it->second.c_str(), str2_it->second.c_str())){
|
||||
S3FS_PRN_EXIT("failed to set access key/secret key.");
|
||||
return -1;
|
||||
}
|
||||
access_key_id = str1_it->second;
|
||||
secret_access_key = str2_it->second;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Read Aws Credential File
|
||||
//
|
||||
bool S3fsCred::ReadAwsCredentialFile(const std::string &filename)
|
||||
bool S3fsCred::ReadAwsCredentialFile(const std::string &filename, AutoLock::Type type)
|
||||
{
|
||||
// open passwd file
|
||||
std::ifstream PF(filename.c_str());
|
||||
@ -652,12 +864,12 @@ bool S3fsCred::ReadAwsCredentialFile(const std::string &filename)
|
||||
S3FS_PRN_EXIT("AWS session token was expected but wasn't provided in aws/credentials file for profile: %s.", aws_profile.c_str());
|
||||
return false;
|
||||
}
|
||||
if(!SetAccessKey(accesskey.c_str(), secret.c_str())){
|
||||
if(!SetAccessKey(accesskey.c_str(), secret.c_str(), type)){
|
||||
S3FS_PRN_EXIT("failed to set internal data for access key/secret key from aws credential file.");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if(!SetAccessKeyWithSessionToken(accesskey.c_str(), secret.c_str(), session_token.c_str())){
|
||||
if(!SetAccessKeyWithSessionToken(accesskey.c_str(), secret.c_str(), session_token.c_str(), type)){
|
||||
S3FS_PRN_EXIT("session token is invalid.");
|
||||
return false;
|
||||
}
|
||||
@ -695,13 +907,13 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
}
|
||||
|
||||
// 1 - keys specified on the command line
|
||||
if(IsSetAccessKeys()){
|
||||
if(IsSetAccessKeys(AutoLock::NONE)){
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2 - was specified on the command line
|
||||
if(IsSetPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile(AutoLock::NONE)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -721,7 +933,7 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
S3FS_PRN_INFO2("access key from env variables");
|
||||
if(AWSSESSIONTOKEN != NULL){
|
||||
S3FS_PRN_INFO2("session token is available");
|
||||
if(!SetAccessKeyWithSessionToken(AWSACCESSKEYID, AWSSECRETACCESSKEY, AWSSESSIONTOKEN)){
|
||||
if(!SetAccessKeyWithSessionToken(AWSACCESSKEYID, AWSSECRETACCESSKEY, AWSSESSIONTOKEN, AutoLock::NONE)){
|
||||
S3FS_PRN_EXIT("session token is invalid.");
|
||||
return false;
|
||||
}
|
||||
@ -732,7 +944,7 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!SetAccessKey(AWSACCESSKEYID, AWSSECRETACCESSKEY)){
|
||||
if(!SetAccessKey(AWSACCESSKEYID, AWSSECRETACCESSKEY, AutoLock::NONE)){
|
||||
S3FS_PRN_EXIT("if one access key is specified, both keys need to be specified.");
|
||||
return false;
|
||||
}
|
||||
@ -748,7 +960,7 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
S3FS_PRN_EXIT("AWS_CREDENTIAL_FILE: \"%s\" is not readable.", passwd_file.c_str());
|
||||
return false;
|
||||
}
|
||||
if(!ReadS3fsPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile(AutoLock::NONE)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -757,7 +969,7 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
|
||||
// 3b - check ${HOME}/.aws/credentials
|
||||
std::string aws_credentials = std::string(getpwuid(getuid())->pw_dir) + "/.aws/credentials";
|
||||
if(ReadAwsCredentialFile(aws_credentials)){
|
||||
if(ReadAwsCredentialFile(aws_credentials, AutoLock::NONE)){
|
||||
return true;
|
||||
}else if(aws_profile != DEFAULT_AWS_PROFILE_NAME){
|
||||
S3FS_PRN_EXIT("Could not find profile: %s in file: %s", aws_profile.c_str(), aws_credentials.c_str());
|
||||
@ -770,14 +982,14 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
passwd_file = HOME;
|
||||
passwd_file += "/.passwd-s3fs";
|
||||
if(IsReadableS3fsPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile(AutoLock::NONE)){
|
||||
return false;
|
||||
}
|
||||
|
||||
// It is possible that the user's file was there but
|
||||
// contained no key pairs i.e. commented out
|
||||
// in that case, go look in the final location
|
||||
if(IsSetAccessKeys()){
|
||||
if(IsSetAccessKeys(AutoLock::NONE)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -786,7 +998,7 @@ bool S3fsCred::InitialS3fsCredentials()
|
||||
// 5 - from the system default location
|
||||
passwd_file = "/etc/passwd-s3fs";
|
||||
if(IsReadableS3fsPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile()){
|
||||
if(!ReadS3fsPasswdFile(AutoLock::NONE)){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -854,23 +1066,37 @@ bool S3fsCred::ParseIAMCredentialResponse(const char* response, iamcredmap_t& ke
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S3fsCred::CheckIAMCredentialUpdate()
|
||||
bool S3fsCred::CheckIAMCredentialUpdate(std::string* access_key_id, std::string* secret_access_key, std::string* access_token)
|
||||
{
|
||||
if(IAM_role.empty() && !is_ecs && !is_ibm_iam_auth){
|
||||
return true;
|
||||
}
|
||||
if(time(NULL) + S3fsCred::IAM_EXPIRE_MERGIN <= AWSAccessTokenExpire){
|
||||
return true;
|
||||
}
|
||||
S3FS_PRN_INFO("IAM Access Token refreshing...");
|
||||
AutoLock auto_lock(&token_lock);
|
||||
|
||||
// update
|
||||
S3fsCurl s3fscurl;
|
||||
if(0 != s3fscurl.GetIAMCredentials()){
|
||||
S3FS_PRN_ERR("IAM Access Token refresh failed");
|
||||
return false;
|
||||
if(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;
|
||||
}
|
||||
S3FS_PRN_INFO("IAM Access Token refreshed");
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
if(access_key_id){
|
||||
*access_key_id = AWSAccessKeyId;
|
||||
}
|
||||
if(secret_access_key){
|
||||
*secret_access_key = AWSSecretAccessKey;
|
||||
}
|
||||
if(access_token){
|
||||
if(IsIBMIAMAuth() || IsSetIAMRole(AutoLock::ALREADY_LOCKED) || is_ecs || is_use_session_token){
|
||||
*access_token = AWSAccessToken;
|
||||
}else{
|
||||
access_token->erase();
|
||||
}
|
||||
}
|
||||
S3FS_PRN_INFO("IAM Access Token refreshed");
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -900,7 +1126,7 @@ int S3fsCred::DetectParam(const char* arg)
|
||||
SetIAMTokenField("\"access_token\"");
|
||||
SetIAMExpiryField("\"expiration\"");
|
||||
SetIAMFieldCount(2);
|
||||
SetIMDSVersion(1);
|
||||
SetIMDSVersion(1, AutoLock::NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -924,7 +1150,7 @@ int S3fsCred::DetectParam(const char* arg)
|
||||
}
|
||||
|
||||
if(0 == strcmp(arg, "imdsv1only")){
|
||||
SetIMDSVersion(1);
|
||||
SetIMDSVersion(1, AutoLock::NONE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -934,14 +1160,14 @@ int S3fsCred::DetectParam(const char* arg)
|
||||
return -1;
|
||||
}
|
||||
SetIsECS(true);
|
||||
SetIMDSVersion(1);
|
||||
SetIMDSVersion(1, AutoLock::NONE);
|
||||
SetIAMCredentialsURL("http://169.254.170.2");
|
||||
SetIAMFieldCount(5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(is_prefix(arg, "iam_role")){
|
||||
if(IsECS() || IsIBMIAMAuth()){
|
||||
if(is_ecs || IsIBMIAMAuth()){
|
||||
S3FS_PRN_EXIT("option iam_role cannot be used in conjunction with ecs or ibm");
|
||||
return -1;
|
||||
}
|
||||
@ -953,7 +1179,7 @@ int S3fsCred::DetectParam(const char* arg)
|
||||
|
||||
}else if(is_prefix(arg, "iam_role=")){
|
||||
const char* role = strchr(arg, '=') + sizeof(char);
|
||||
SetIAMRole(role);
|
||||
SetIAMRole(role, AutoLock::NONE);
|
||||
SetIAMRoleMetadataType(false);
|
||||
return 0;
|
||||
}
|
||||
@ -1014,21 +1240,21 @@ bool S3fsCred::CheckAllParams()
|
||||
}
|
||||
|
||||
// error checking of command line arguments for compatibility
|
||||
if(S3fsCurl::IsPublicBucket() && IsSetAccessKeys()){
|
||||
if(S3fsCurl::IsPublicBucket() && IsSetAccessKeys(AutoLock::NONE)){
|
||||
S3FS_PRN_EXIT("specifying both public_bucket and the access keys options is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(IsSetPasswdFile() && IsSetAccessKeys()){
|
||||
if(IsSetPasswdFile() && IsSetAccessKeys(AutoLock::NONE)){
|
||||
S3FS_PRN_EXIT("specifying both passwd_file and the access keys options is invalid.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!S3fsCurl::IsPublicBucket() && !IsIAMRoleMetadataType() && !IsECS()){
|
||||
if(!S3fsCurl::IsPublicBucket() && !load_iamrole && !is_ecs){
|
||||
if(!InitialS3fsCredentials()){
|
||||
return false;
|
||||
}
|
||||
if(!IsSetAccessKeys()){
|
||||
if(!IsSetAccessKeys(AutoLock::NONE)){
|
||||
S3FS_PRN_EXIT("could not establish security credentials, check documentation.");
|
||||
return false;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#ifndef S3FS_CRED_H_
|
||||
#define S3FS_CRED_H_
|
||||
|
||||
#include "autolock.h"
|
||||
|
||||
//----------------------------------------------
|
||||
// Typedefs
|
||||
//----------------------------------------------
|
||||
@ -43,37 +45,39 @@ class S3fsCred
|
||||
static const char* AWS_SECRETKEY;
|
||||
|
||||
static const int IAM_EXPIRE_MERGIN;
|
||||
static const char* ECS_IAM_ENV_VAR;
|
||||
static const char* IAMCRED_ACCESSKEYID;
|
||||
static const char* IAMCRED_SECRETACCESSKEY;
|
||||
static const char* IAMCRED_ROLEARN;
|
||||
|
||||
static std::string bucket_name;
|
||||
|
||||
pthread_mutex_t token_lock;
|
||||
bool is_lock_init;
|
||||
|
||||
std::string passwd_file;
|
||||
std::string aws_profile;
|
||||
|
||||
bool load_iamrole;
|
||||
|
||||
std::string AWSAccessKeyId;
|
||||
std::string AWSSecretAccessKey;
|
||||
std::string AWSAccessToken;
|
||||
time_t AWSAccessTokenExpire;
|
||||
std::string AWSAccessKeyId; // Protect exclusively
|
||||
std::string AWSSecretAccessKey; // Protect exclusively
|
||||
std::string AWSAccessToken; // Protect exclusively
|
||||
time_t AWSAccessTokenExpire; // Protect exclusively
|
||||
|
||||
bool is_ecs;
|
||||
bool is_use_session_token;
|
||||
bool is_ibm_iam_auth;
|
||||
|
||||
std::string IAM_cred_url;
|
||||
int IAM_api_version;
|
||||
std::string IAMv2_api_token;
|
||||
int IAM_api_version; // Protect exclusively
|
||||
std::string IAMv2_api_token; // Protect exclusively
|
||||
size_t IAM_field_count;
|
||||
std::string IAM_token_field;
|
||||
std::string IAM_expiry_field;
|
||||
std::string IAM_role;
|
||||
std::string IAM_role; // Protect exclusively
|
||||
|
||||
public:
|
||||
static const char* ECS_IAM_ENV_VAR;
|
||||
|
||||
static const char* IAMv2_token_url;
|
||||
static int IAMv2_token_ttl;
|
||||
static const char* IAMv2_token_ttl_hdr;
|
||||
@ -87,16 +91,24 @@ class S3fsCred
|
||||
bool SetAwsProfileName(const char* profile_name);
|
||||
bool SetIAMRoleMetadataType(bool flag);
|
||||
|
||||
bool SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey);
|
||||
bool SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken);
|
||||
bool IsSetAccessKeys() const;
|
||||
bool SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey, AutoLock::Type type);
|
||||
bool SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken, AutoLock::Type type);
|
||||
bool IsSetAccessKeys(AutoLock::Type type);
|
||||
|
||||
bool SetIsECS(bool flag);
|
||||
bool SetIsUseSessionToken(bool flag);
|
||||
|
||||
bool SetIsIBMIAMAuth(bool flag);
|
||||
|
||||
std::string SetIAMRole(const char* role);
|
||||
int SetIMDSVersion(int version, AutoLock::Type type);
|
||||
int GetIMDSVersion(AutoLock::Type type);
|
||||
|
||||
bool SetIAMv2APIToken(const std::string& token, AutoLock::Type type);
|
||||
std::string GetIAMv2APIToken(AutoLock::Type type);
|
||||
|
||||
bool SetIAMRole(const char* role, AutoLock::Type type);
|
||||
std::string GetIAMRole(AutoLock::Type type);
|
||||
bool IsSetIAMRole(AutoLock::Type type);
|
||||
size_t SetIAMFieldCount(size_t field_count);
|
||||
std::string SetIAMCredentialsURL(const char* url);
|
||||
std::string SetIAMTokenField(const char* token_field);
|
||||
@ -105,14 +117,19 @@ class S3fsCred
|
||||
bool IsReadableS3fsPasswdFile();
|
||||
bool CheckS3fsPasswdFilePerms();
|
||||
bool ParseS3fsPasswdFile(bucketkvmap_t& resmap);
|
||||
bool ReadS3fsPasswdFile();
|
||||
bool ReadS3fsPasswdFile(AutoLock::Type type);
|
||||
|
||||
int CheckS3fsCredentialAwsFormat(const kvmap_t& kvmap);
|
||||
bool ReadAwsCredentialFile(const std::string &filename);
|
||||
int CheckS3fsCredentialAwsFormat(const kvmap_t& kvmap, std::string& access_key_id, std::string& secret_access_key);
|
||||
bool ReadAwsCredentialFile(const std::string &filename, AutoLock::Type type);
|
||||
|
||||
bool InitialS3fsCredentials();
|
||||
bool ParseIAMCredentialResponse(const char* response, iamcredmap_t& keyval);
|
||||
|
||||
bool GetIAMCredentialsURL(std::string& url, bool check_iam_role, AutoLock::Type type);
|
||||
bool LoadIAMCredentials(AutoLock::Type type);
|
||||
bool SetIAMCredentials(const char* response, AutoLock::Type type);
|
||||
bool SetIAMRoleFromMetaData(const char* response, AutoLock::Type type);
|
||||
|
||||
bool CheckForbiddenBucketParams();
|
||||
|
||||
public:
|
||||
@ -122,27 +139,11 @@ class S3fsCred
|
||||
S3fsCred();
|
||||
~S3fsCred();
|
||||
|
||||
bool IsIAMRoleMetadataType() const { return load_iamrole; }
|
||||
const std::string& GetAccessKeyID() const { return AWSAccessKeyId; }
|
||||
const std::string& GetSecretAccessKey() const { return AWSSecretAccessKey; }
|
||||
const std::string& GetAccessToken() const { return AWSAccessToken; }
|
||||
|
||||
bool IsECS() const { return is_ecs; }
|
||||
bool IsUseSessionToken() const { return is_use_session_token; }
|
||||
|
||||
bool IsIBMIAMAuth() const { return is_ibm_iam_auth; }
|
||||
|
||||
const std::string& GetIAMRole() const { return IAM_role; }
|
||||
const std::string& GetIAMCredentialsURL() const { return IAM_cred_url; }
|
||||
int SetIMDSVersion(int version);
|
||||
int GetIMDSVersion() const { return IAM_api_version; }
|
||||
bool LoadIAMRoleFromMetaData();
|
||||
|
||||
bool SetIAMv2APIToken(const char* response);
|
||||
const std::string& GetIAMv2APIToken() const { return IAMv2_api_token; }
|
||||
bool SetIAMCredentials(const char* response);
|
||||
bool SetIAMRoleFromMetaData(const char* response);
|
||||
|
||||
bool CheckIAMCredentialUpdate();
|
||||
bool CheckIAMCredentialUpdate(std::string* access_key_id = NULL, std::string* secret_access_key = NULL, std::string* access_token = NULL);
|
||||
|
||||
int DetectParam(const char* arg);
|
||||
bool CheckAllParams();
|
||||
|
Loading…
x
Reference in New Issue
Block a user