Commit 29e054fc authored by Nikola Hardi's avatar Nikola Hardi
Browse files

Sync the credentials manager with libjalienO2

parent 5d0aa817
Pipeline #2445693 passed with stage
in 6 minutes and 25 seconds
// Author: Nikola Hardi 3/6/2019
#ifndef ROOT_TJAlienCredentials
#define ROOT_TJAlienCredentials
#include <string>
#include <cstring>
#include <iostream>
#include <map>
#include <string>
#include <termios.h>
#include "TObject.h"
using std::string;
#define __FILENAMEEXT__ \
(strrchr(__FILE__, '/') ? std::string(strrchr(__FILE__, '/') + 1) \
: std::string(__FILE__))
#define __FILENAME__ __FILENAMEEXT__.substr(0, __FILENAMEEXT__.find('.'))
#define INFO(message) \
std::cout << "\rInfo in <" << __FILENAME__ << "::" << __func__ \
<< ">: " << message << std::endl
#define ERROR(message) \
std::cerr << "\rError in <" << __FILENAME__ << "::" << __func__ \
<< ">: " << message << std::endl
using std::map;
using std::string;
enum CredentialsKind { cJBOX_TOKEN = 0,
cFULL_GRID_CERT,
cJOB_TOKEN,
cOTHER_TOKEN,
enum CredentialsKind {
cNOT_FOUND = -1,
cJBOX_TOKEN = 0,
cFULL_GRID_CERT,
cJOB_TOKEN,
cOTHER_TOKEN,
};
class TJAlienCredentialsObject {
public:
string certpath;
string keypath;
string password;
CredentialsKind kind;
bool autoremove;
public:
string certpath;
string keypath;
string password;
CredentialsKind kind;
bool autoremove;
TJAlienCredentialsObject() {}
TJAlienCredentialsObject(string certpath,
string keypath,
CredentialsKind kind = cOTHER_TOKEN,
bool autoremove = false)
{
this->certpath = certpath;
this->keypath = keypath;
this->kind = kind;
this->autoremove = autoremove;
};
TJAlienCredentialsObject() {}
void wipe() {
if(autoremove) {
if(gDebug) printf("removing safe files: %s %s\n", certpath.c_str(), keypath.c_str());
remove(certpath.c_str());
remove(keypath.c_str());
}
TJAlienCredentialsObject(string certpath, string keypath,
CredentialsKind kind = cOTHER_TOKEN,
bool autoremove = false) {
this->certpath = certpath;
this->keypath = keypath;
this->kind = kind;
this->autoremove = autoremove;
};
void wipe() {
if (autoremove) {
int gDebug = std::getenv("gDebug") ? std::stoi(std::getenv("gDebug")) : 0;
if (gDebug)
INFO("removing safe files: " << certpath.c_str() << keypath.c_str());
remove(certpath.c_str());
remove(keypath.c_str());
}
}
bool exists();
const string getKey();
const string getCertificate();
const string getPassword();
void readPassword();
bool exists();
const string getKey();
const string getCertificate();
const string getPassword();
void readPassword();
};
class TJAlienCredentials : public TObject {
class TJAlienCredentials {
public:
TJAlienCredentials();
~TJAlienCredentials();
......@@ -60,10 +74,15 @@ public:
static string getHomeDir();
void loadCredentials();
bool has(CredentialsKind kind);
TJAlienCredentialsObject get(CredentialsKind kind);
bool has(CredentialsKind kind) const;
TJAlienCredentialsObject get(CredentialsKind kind) const;
TJAlienCredentialsObject get();
void removeCredentials(CredentialsKind kind);
short count();
void selectPreferedCredentials();
CredentialsKind getPreferedCredentials() const;
const string& getMessages() const;
bool checkCertValidity(const char *path);
static const char *ENV_JOBTOKEN_KEY;
static const char *ENV_JOBTOKEN_CERT;
......@@ -71,6 +90,7 @@ public:
static const char *TMP_JOBTOKEN_CERT_FNAME_PREFIX;
private:
CredentialsKind preferedCredentials;
void loadTokenCertificate();
void loadFullGridCertificate();
void loadJobTokenCertificate();
......@@ -79,13 +99,12 @@ private:
string getTokencertPath();
string getTokenkeyPath();
string getSafeFilename(const string& prefix);
void writeSafeFile(const string& filepath, const string& content);
string getSafeFilename(const string &prefix);
void writeSafeFile(const string &filepath, const string &content);
string tmpdir;
string homedir;
string msg;
map<CredentialsKind, TJAlienCredentialsObject> found_credentials;
ClassDef(TJAlienCredentials, 0)
};
#endif
#include "TJAlienCredentials.h"
#include <sstream>
#include <cerrno>
#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <fstream>
#include <cstdlib>
#include <iostream>
#include <fcntl.h>
#include <sstream>
#include <unistd.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
using std::endl;
using std::getenv;
using std::ifstream;
using std::ofstream;
using std::stringstream;
using std::endl;
using std::getenv;
const char* TJAlienCredentials::ENV_JOBTOKEN_KEY = "JALIEN_TOKEN_KEY";
const char* TJAlienCredentials::ENV_JOBTOKEN_CERT = "JALIEN_TOKEN_CERT";
const char *TJAlienCredentials::ENV_JOBTOKEN_KEY = "JALIEN_TOKEN_KEY";
const char *TJAlienCredentials::ENV_JOBTOKEN_CERT = "JALIEN_TOKEN_CERT";
const char* TJAlienCredentials::TMP_JOBTOKEN_KEY_FNAME_PREFIX = "tmpjobtokenkey_";
const char* TJAlienCredentials::TMP_JOBTOKEN_CERT_FNAME_PREFIX = "tmpjobtokencert_";
const char *TJAlienCredentials::TMP_JOBTOKEN_KEY_FNAME_PREFIX =
"tmpjobtokenkey_";
const char *TJAlienCredentials::TMP_JOBTOKEN_CERT_FNAME_PREFIX =
"tmpjobtokencert_";
bool fileExists(const string &filename)
{
bool fileExists = false;
FILE *f = fopen(filename.c_str(), "r");
bool fileExists(const string &filename) {
bool fileExists = false;
FILE *f = fopen(filename.c_str(), "r");
if (f != NULL ) {
fclose(f);
fileExists = true;
} else {
fileExists = false;
}
if (f != NULL) {
fclose(f);
fileExists = true;
} else {
fileExists = false;
}
return fileExists;
return fileExists;
}
bool TJAlienCredentialsObject::exists() {
return fileExists(certpath) && fileExists(keypath);
return fileExists(certpath) && fileExists(keypath);
}
void TJAlienCredentials::writeSafeFile(const string& filename, const string& content) {
if(gDebug) printf("writing safe file %s\n", filename.c_str());
int fd = open(filename.c_str(), O_RDWR | O_CREAT, 0600);
write(fd, content.c_str(), content.length());
close(fd);
void TJAlienCredentials::writeSafeFile(const string &filename,
const string &content) {
int gDebug = std::getenv("gDebug") ? std::stoi(std::getenv("gDebug")) : 0;
if (gDebug)
INFO("writing safe file " << filename.c_str());
int fd = open(filename.c_str(), O_RDWR | O_CREAT, 0600);
if (write(fd, content.c_str(), content.length()) == -1)
if (gDebug)
ERROR("writing safe file failed: " << std::strerror(errno));
close(fd);
}
string TJAlienCredentials::getSafeFilename(const string& prefix) {
string filename = TJAlienCredentials::getTmpDir() + "/" + prefix;
const char *JOB_ID = getenv("ALIEN_PROC_ID");
string TJAlienCredentials::getSafeFilename(const string &prefix) {
string filename = TJAlienCredentials::getTmpDir() + "/" + prefix;
if(JOB_ID != NULL) {
filename += JOB_ID;
} else {
pid_t pid = getpid();
unsigned int rnd = random() % 100 + 1;
const char *JOB_ID = getenv("ALIEN_PROC_ID");
do {
filename += std::to_string(pid) + "_" + std::to_string(rnd);
} while(fileExists(filename));
}
if (JOB_ID != NULL) {
filename += JOB_ID;
} else {
pid_t pid = getpid();
unsigned int rnd = random() % 100 + 1;
do {
filename += std::to_string(pid) + "_" + std::to_string(rnd);
} while (fileExists(filename));
}
return filename;
return filename;
}
string TJAlienCredentials::getTmpDir() {
string tmpdir;
std::string TJAlienCredentials::getTmpDir() {
std::string tmpdir;
if (getenv("TMPDIR") != NULL)
tmpdir = getenv("TMPDIR");
else if (getenv("TMP") != NULL)
tmpdir = getenv("TMP");
else if (getenv("TEMP") != NULL)
tmpdir = getenv("TEMP");
else
tmpdir = P_tmpdir;
if (getenv("TMPDIR") != NULL)
tmpdir = getenv("TMPDIR");
else if (getenv("TMP") != NULL)
tmpdir = getenv("TMP");
else if (getenv("TEMP") != NULL)
tmpdir = getenv("TEMP");
else
tmpdir = P_tmpdir;
return tmpdir;
return tmpdir;
}
string TJAlienCredentials::getHomeDir() {
string homedir;
std::string TJAlienCredentials::getHomeDir() {
std::string homedir;
if (getenv("HOME") != NULL)
homedir = getenv("HOME");
else
homedir = "~";
if (getenv("HOME") != NULL)
homedir = getenv("HOME");
else
homedir = "~";
return homedir;
return homedir;
}
string TJAlienCredentials::getTokencertPath()
{
std::stringstream tokencert_s;
tokencert_s << tmpdir << "/tokencert_" << getuid() << ".pem";
std::string tokencert = tokencert_s.str();
std::string tokencertpath = std::getenv("JALIEN_TOKEN_CERT") ? : tokencert;
std::string TJAlienCredentials::getTokencertPath() {
std::stringstream tokencert_s;
tokencert_s << tmpdir << "/tokencert_" << getuid() << ".pem";
std::string tokencert = tokencert_s.str();
std::string tokencertpath = std::getenv("JALIEN_TOKEN_CERT") ?: tokencert;
return tokencertpath;
return tokencertpath;
}
string TJAlienCredentials::getTokenkeyPath()
{
std::stringstream tokenkey_s;
tokenkey_s << tmpdir << "/tokenkey_" << getuid() << ".pem";
std::string tokenkey = tokenkey_s.str();
std::string tokenkeypath = std::getenv("JALIEN_TOKEN_KEY") ? : tokenkey;
std::string TJAlienCredentials::getTokenkeyPath() {
std::stringstream tokenkey_s;
tokenkey_s << tmpdir << "/tokenkey_" << getuid() << ".pem";
std::string tokenkey = tokenkey_s.str();
std::string tokenkeypath = std::getenv("JALIEN_TOKEN_KEY") ?: tokenkey;
return tokenkeypath;
return tokenkeypath;
}
string TJAlienCredentials::getUsercertPath()
{
std::string usercert = homedir + "/.globus/usercert.pem";
std::string usercertpath = std::getenv("X509_USER_CERT") ? : usercert;
return usercertpath;
std::string TJAlienCredentials::getUsercertPath() {
std::string usercert = homedir + "/.globus/usercert.pem";
std::string usercertpath = std::getenv("X509_USER_CERT") ?: usercert;
return usercertpath;
}
string TJAlienCredentials::getUserkeyPath()
{
std::string userkey = homedir + "/.globus/userkey.pem";
std::string userkeypath = std::getenv("X509_USER_KEY") ? : userkey;
return userkeypath;
string TJAlienCredentials::getUserkeyPath() {
std::string userkey = homedir + "/.globus/userkey.pem";
std::string userkeypath = std::getenv("X509_USER_KEY") ?: userkey;
return userkeypath;
}
TJAlienCredentials::TJAlienCredentials() {
tmpdir = getTmpDir();
homedir = getHomeDir();
tmpdir = getTmpDir();
homedir = getHomeDir();
}
void TJAlienCredentials::loadCredentials() {
removeCredentials(cJOB_TOKEN);
found_credentials.clear();
loadTokenCertificate();
loadFullGridCertificate();
loadJobTokenCertificate();
found_credentials.clear();
loadTokenCertificate();
loadFullGridCertificate();
loadJobTokenCertificate();
}
void TJAlienCredentials::loadTokenCertificate() {
TJAlienCredentialsObject token_credentials(getTokencertPath(), getTokenkeyPath(), cJBOX_TOKEN);
TJAlienCredentialsObject token_credentials(getTokencertPath(),
getTokenkeyPath(), cJBOX_TOKEN);
if(token_credentials.exists()) {
found_credentials[cJBOX_TOKEN] = token_credentials;
}
if (token_credentials.exists()) {
found_credentials[cJBOX_TOKEN] = token_credentials;
}
}
void TJAlienCredentials::loadFullGridCertificate() {
TJAlienCredentialsObject grid_certificate(getUsercertPath(), getUserkeyPath(), cFULL_GRID_CERT);
TJAlienCredentialsObject grid_certificate(getUsercertPath(), getUserkeyPath(),
cFULL_GRID_CERT);
if (grid_certificate.exists()) {
found_credentials[cFULL_GRID_CERT] = grid_certificate;
}
if (grid_certificate.exists()) {
found_credentials[cFULL_GRID_CERT] = grid_certificate;
}
}
void TJAlienCredentials::loadJobTokenCertificate() {
const char *env_cert = getenv(ENV_JOBTOKEN_CERT);
const char *env_key = getenv(ENV_JOBTOKEN_KEY);
const char *env_cert = getenv(ENV_JOBTOKEN_CERT);
const char *env_key = getenv(ENV_JOBTOKEN_KEY);
// if it doesn't have both environment variables
if (!env_cert || !env_key) {
return;
}
// environment variables contain valid filepaths instead of the actual token
if (fileExists(env_cert) && fileExists(env_key)) {
found_credentials[cJOB_TOKEN] =
TJAlienCredentialsObject(env_cert, env_key, cJOB_TOKEN);
} else {
const string &tmpcertpath = getSafeFilename(TMP_JOBTOKEN_CERT_FNAME_PREFIX);
writeSafeFile(tmpcertpath, env_cert);
const string &tmpkeypath = getSafeFilename(TMP_JOBTOKEN_KEY_FNAME_PREFIX);
writeSafeFile(tmpkeypath, env_key);
found_credentials[cJOB_TOKEN] =
TJAlienCredentialsObject(tmpcertpath, tmpkeypath, cJOB_TOKEN, true);
}
}
// if it doesn't have both environment variables
if(!env_cert || !env_key) {
return;
}
bool TJAlienCredentials::has(CredentialsKind kind) const {
return found_credentials.count(kind) == 1;
}
// environment variables contain valid filepaths instead of the actual token
if(fileExists(env_cert) && fileExists(env_key)) {
found_credentials[cJOB_TOKEN] = TJAlienCredentialsObject(env_cert, env_key, cJOB_TOKEN);
} else {
const string& tmpcertpath = getSafeFilename(TMP_JOBTOKEN_CERT_FNAME_PREFIX);
writeSafeFile(tmpcertpath, env_cert);
TJAlienCredentialsObject TJAlienCredentials::get(CredentialsKind kind) const {
if (this->has(kind)) {
return found_credentials.at(kind);
} else {
return TJAlienCredentialsObject();
}
}
const string& tmpkeypath = getSafeFilename(TMP_JOBTOKEN_KEY_FNAME_PREFIX);
writeSafeFile(tmpkeypath, env_key);
TJAlienCredentialsObject TJAlienCredentials::get() {
if (this->has(cJOB_TOKEN)) {
return this->get(cJOB_TOKEN);
} else if (this->has(cJBOX_TOKEN)) {
return this->get(cJBOX_TOKEN);
} else if (this->has(cFULL_GRID_CERT)) {
TJAlienCredentialsObject co = this->get(cFULL_GRID_CERT);
if (co.password.empty())
co.readPassword();
return co;
} else {
ERROR("Failed to get any credentials");
return TJAlienCredentialsObject();
}
}
void TJAlienCredentials::removeCredentials(CredentialsKind kind) {
if (this->has(kind)) {
if (kind == cJOB_TOKEN)
get(kind).wipe();
found_credentials.erase(kind);
}
}
short TJAlienCredentials::count() { return found_credentials.size(); }
found_credentials[cJOB_TOKEN] = TJAlienCredentialsObject(tmpcertpath, tmpkeypath, cJOB_TOKEN, true);
std::string readFile(const char *filename) {
std::string line;
std::stringstream contents;
std::ifstream f(filename);
if (f.is_open()) {
while (getline(f, line)) {
contents << line << std::endl;
}
}
return contents.str();
}
const std::string TJAlienCredentialsObject::getKey() {
return readFile(keypath.c_str());
}
bool TJAlienCredentials::has(CredentialsKind kind) {
return found_credentials.count(kind) == 1;
const std::string TJAlienCredentialsObject::getCertificate() {
return readFile(certpath.c_str());
}
TJAlienCredentialsObject TJAlienCredentials::get(CredentialsKind kind) {
if(this->has(kind)) {
return found_credentials[kind];
void TJAlienCredentialsObject::readPassword() {
if (this->kind == cFULL_GRID_CERT &&
this->getKey().find("ENCRYPTED") != std::string::npos) {
printf("[Grid certificate password: ]");
struct termios termold, termnew;
tcgetattr(fileno(stdin), &termold);
termnew = termold;
termnew.c_lflag &= ~ECHO;
termnew.c_lflag |= ECHONL;
tcsetattr(fileno(stdin), TCSANOW, &termnew);
char password[64];
if (fgets(password, sizeof(password), stdin) != nullptr) {
tcsetattr(0, TCSANOW, &termold);
password[strlen(password) - 1] = 0;
this->password = std::string(password);
} else {
return TJAlienCredentialsObject();
ERROR("Error while reading from stdin");
this->password = "";
}
} else
this->password = "";
}
void TJAlienCredentials::removeCredentials(CredentialsKind kind) {
if (this->has(kind)) {
if(kind == cJOB_TOKEN)
get(kind).wipe();
const std::string TJAlienCredentialsObject::getPassword() {
if (this->password.empty())
readPassword();
found_credentials.erase(kind);
}
return this->password;
}
short TJAlienCredentials::count() {
return found_credentials.size();
TJAlienCredentials::~TJAlienCredentials() {
removeCredentials(cJOB_TOKEN);
}
string readFile(const char* filename) {
string line;
stringstream contents;
ifstream f(filename);
void TJAlienCredentials::selectPreferedCredentials() {
msg = "";
if(has(cJOB_TOKEN)) {
preferedCredentials = cJOB_TOKEN;
return;
}
if(f.is_open()) {
while(getline(f, line)) {
contents << line << endl;
}
if (has(cJBOX_TOKEN)) {
if(!checkCertValidity(getTokencertPath().c_str())) {
msg += "Token certificate is invalid or expired and it should be renewed.\n";
} else {
preferedCredentials = cJBOX_TOKEN;
return;
}
return contents.str();
}
}
if (has(cFULL_GRID_CERT)) {
msg += "Fallback to full grid cert - please use alien-token-init or TGrid::Connect() to renew it.\n";
preferedCredentials = cFULL_GRID_CERT;
return;
}
const string TJAlienCredentialsObject::getKey() {
return readFile(keypath.c_str());
msg += "Failed to find any credentials\n";
preferedCredentials = cNOT_FOUND;
}
const string TJAlienCredentialsObject::getCertificate() {
return readFile(certpath.c_str());
CredentialsKind TJAlienCredentials::getPreferedCredentials() const {
return preferedCredentials;
}
void TJAlienCredentialsObject::readPassword() {
if (this->kind == cFULL_GRID_CERT && this->getKey().find("ENCRYPTED") != std::string::npos)
{
printf("[Grid certificate password: ]");
struct termios termold, termnew;
tcgetattr(fileno(stdin), &termold);
termnew = termold;