// ---------------------------------------------------------------------- // File: UserCredentialFactory.cc // Author: Georgios Bitzes - CERN // ---------------------------------------------------------------------- /************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2011 CERN/Switzerland * * * * 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 3 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, see .* ************************************************************************/ #include "UserCredentialFactory.hh" #include "Logbook.hh" #include "Utils.hh" //------------------------------------------------------------------------------ // Constructor //------------------------------------------------------------------------------ UserCredentialFactory::UserCredentialFactory(const CredentialConfig &conf) : config(conf) {} //------------------------------------------------------------------------------ // Generate SearchOrder from environment variables, while taking into account // EOS_FUSE_CREDS. //------------------------------------------------------------------------------ SearchOrder UserCredentialFactory::parse(LogbookScope &scope, const JailIdentifier& id, const Environment &env, uid_t uid, gid_t gid) { SearchOrder retval; std::string credString = env.get("EOS_FUSE_CREDS"); if(credString.empty()) { // Use defaults. parseSingle(scope, "defaults", id, env, uid, gid, retval); return retval; } std::vector parts = eos::common::StringSplit>(credString, ","); for(auto it = parts.begin(); it != parts.end(); it++) { parseSingle(scope, *it, id, env, uid, gid, retval); } return retval; } //------------------------------------------------------------------------------ // Append krb5 UserCredentials built from KRB5CCNAME-equivalent string. //------------------------------------------------------------------------------ void UserCredentialFactory::addKrb5(const JailIdentifier &id, std::string path, uid_t uid, gid_t gid, SearchOrder &out, const std::string& key) { if(!config.use_user_krb5cc || path.empty()) { return; } //---------------------------------------------------------------------------- // Kerberos keyring? //---------------------------------------------------------------------------- if(startsWith(path, "KEYRING")) { out.emplace_back(UserCredentials::MakeKrk5(path, uid, gid, key)); return; } //---------------------------------------------------------------------------- // Kerberos kcm? //---------------------------------------------------------------------------- if(startsWith(path, "KCM")) { out.emplace_back(UserCredentials::MakeKcm(path, uid, gid, key)); return; } //---------------------------------------------------------------------------- // Drop FILE:, if exists //---------------------------------------------------------------------------- const std::string prefix = "FILE:"; if(startsWith(path, prefix)) { path = path.substr(prefix.size()); } if(path.empty()) { //-------------------------------------------------------------------------- // Early exit, nothing to add to search order. //-------------------------------------------------------------------------- return; } out.emplace_back(UserCredentials::MakeKrb5(id, path, uid, gid, key)); return; } //------------------------------------------------------------------------------ // Append OAUTH2 UserCredentials built from KRB5CCNAME-equivalent string. //------------------------------------------------------------------------------ void UserCredentialFactory::addOAUTH2(const JailIdentifier &id, std::string path, uid_t uid, gid_t gid, SearchOrder &out, const std::string& key) { if(!config.use_user_oauth2 || path.empty()) { return; } //---------------------------------------------------------------------------- // Drop FILE:, if exists //---------------------------------------------------------------------------- const std::string prefix = "FILE:"; if(startsWith(path, prefix)) { path = path.substr(prefix.size()); } if(path.empty()) { //-------------------------------------------------------------------------- // Early exit, nothing to add to search order. //-------------------------------------------------------------------------- return; } out.emplace_back(UserCredentials::MakeOAUTH2(id, path, uid, gid, key)); return; } //------------------------------------------------------------------------------ // Append ZTN UserCredentials built from KRB5CCNAME-equivalent string. //------------------------------------------------------------------------------ void UserCredentialFactory::addZTN(const JailIdentifier &id, std::string path, uid_t uid, gid_t gid, SearchOrder &out, const std::string& key) { if(!config.use_user_ztn || path.empty()) { return; } //---------------------------------------------------------------------------- // Drop FILE:, if exists //---------------------------------------------------------------------------- const std::string prefix = "FILE:"; if(startsWith(path, prefix)) { path = path.substr(prefix.size()); } if(path.empty()) { //-------------------------------------------------------------------------- // Early exit, nothing to add to search order. //-------------------------------------------------------------------------- return; } out.emplace_back(UserCredentials::MakeZTN(id, path, uid, gid, key)); return; } //------------------------------------------------------------------------------ // Append krb5 UserCredentials built from Environment, if KRB5CCNAME // is defined. //------------------------------------------------------------------------------ void UserCredentialFactory::addKrb5FromEnv(const JailIdentifier &id, const Environment& env, uid_t uid, gid_t gid, SearchOrder &out) { std::string key = env.get("EOS_FUSE_SECRET"); if (key.empty() && config.encryptionKey.length()) { key = config.encryptionKey; } return addKrb5(id, env.get("KRB5CCNAME"), uid, gid, out, key); } //------------------------------------------------------------------------------ // Append OAUTH2 UserCredentials built from Environment, if OAUHT2_TOKEN // is defined. //------------------------------------------------------------------------------ void UserCredentialFactory::addOAUTH2FromEnv(const JailIdentifier &id, const Environment& env, uid_t uid, gid_t gid, SearchOrder &out) { std::string key = env.get("EOS_FUSE_SECRET"); if (key.empty() && config.encryptionKey.length()) { key = config.encryptionKey; } return addOAUTH2(id, env.get("OAUTH2_TOKEN"), uid, gid, out, key); } //------------------------------------------------------------------------------ // Append ztn UserCredentials built from Environment, if // is defined. //------------------------------------------------------------------------------ void UserCredentialFactory::addZTNFromEnv(const JailIdentifier &id, const Environment& env, uid_t uid, gid_t gid, SearchOrder &out) { std::string key = env.get("EOS_FUSE_SECRET"); std::string btf = env.get("BEARER_TOKEN_FILE"); std::string btfd = env.get("XDG_RUNTIME_DIR"); std::string path; if (btf.length()) { path = btf; } else if (btfd.length()){ path = btfd + std::string("/bt_u") + std::to_string(uid); } return addZTN(id, path, uid, gid, out, key); } //------------------------------------------------------------------------------ // Append krb5 UserCredentials built from X509_USER_PROXY-equivalent string. //------------------------------------------------------------------------------ void UserCredentialFactory::addx509(const JailIdentifier &id, const std::string &path, uid_t uid, gid_t gid, SearchOrder &out, const std::string& key) { if(!config.use_user_gsiproxy || path.empty()) { return; } out.emplace_back(UserCredentials::MakeX509(id, path, uid, gid, key)); return; } //------------------------------------------------------------------------------ // Append UserCredentials object built from X509_USER_PROXY //------------------------------------------------------------------------------ void UserCredentialFactory::addx509FromEnv(const JailIdentifier &id, const Environment& env, uid_t uid, gid_t gid, SearchOrder &out) { std::string key = env.get("EOS_FUSE_SECRET"); if (key.empty() && config.encryptionKey.length()) { key = config.encryptionKey; } return addx509(id, env.get("X509_USER_PROXY"), uid, gid, out, key); } //------------------------------------------------------------------------------ // Populate SearchOrder with entries given in environment variables. //------------------------------------------------------------------------------ void UserCredentialFactory::addDefaultsFromEnv(const JailIdentifier &id, const Environment& env, uid_t uid, gid_t gid, SearchOrder &searchOrder) { std::string key = env.get("EOS_FUSE_SECRET"); if (key.empty() && config.encryptionKey.length()) { key = config.encryptionKey; } //---------------------------------------------------------------------------- // Using SSS? If so, add first. //---------------------------------------------------------------------------- if(config.use_user_sss) { std::string endorsement = env.get("XrdSecsssENDORSEMENT"); searchOrder.emplace_back( UserCredentials::MakeSSS(endorsement, uid, gid, key)); } //---------------------------------------------------------------------------- // Add krb5, x509 derived from environment variables //---------------------------------------------------------------------------- addKrb5AndX509FromEnv(id, env, uid, gid, searchOrder); //---------------------------------------------------------------------------- // Add oauth2 derived from environment variables if (config.use_user_oauth2) { addOAUTH2FromEnv(id, env, uid, gid, searchOrder); } } //------------------------------------------------------------------------------ //! Append UserCredentials object built from krb5, and x509 env variables //------------------------------------------------------------------------------ void UserCredentialFactory::addKrb5AndX509FromEnv(const JailIdentifier &id, const Environment &env, uid_t uid, gid_t gid, SearchOrder &out) { if(config.tryKrb5First) { addKrb5FromEnv(id, env, uid, gid, out); addx509FromEnv(id, env, uid, gid, out); } else { addx509FromEnv(id, env, uid, gid, out); addKrb5FromEnv(id, env, uid, gid, out); } } //------------------------------------------------------------------------------ // Given a single entry of the search path, append any entries // into the given SearchOrder object //------------------------------------------------------------------------------ bool UserCredentialFactory::parseSingle(LogbookScope &scope, const std::string &str, const JailIdentifier &id, const Environment& env, uid_t uid, gid_t gid, SearchOrder &out) { std::string key = env.get("EOS_FUSE_SECRET"); if (key.empty() && config.encryptionKey.length()) { key = config.encryptionKey; } //---------------------------------------------------------------------------- // Defaults? //---------------------------------------------------------------------------- if(str == "defaults") { addDefaultsFromEnv(id, env, uid, gid, out); return true; } //---------------------------------------------------------------------------- // KRB? //---------------------------------------------------------------------------- const std::string krbPrefix = "krb:"; if(startsWith(str, krbPrefix)) { addKrb5(id, str.substr(krbPrefix.size()), uid, gid, out, key); return true; } //---------------------------------------------------------------------------- // X509? //---------------------------------------------------------------------------- const std::string x509Prefix = "x509:"; if(startsWith(str, x509Prefix)) { addx509(id, str.substr(x509Prefix.size()), uid, gid, out, key); return true; } //---------------------------------------------------------------------------- // ZTN? //---------------------------------------------------------------------------- const std::string ztnPrefix = "ztn:"; if(startsWith(str, ztnPrefix)) { addZTN(id, str.substr(ztnPrefix.size()), uid, gid, out, key); return true; } //---------------------------------------------------------------------------- // Cannot parse given string //---------------------------------------------------------------------------- LOGBOOK_INSERT(scope, "Cannot understand this part of EOS_FUSE_CREDS, skipping: " << str); return false; }