This demo consists of 1. An user-friendly library for getting Intel Attestation Service (IAS) report. 2. A application that uses this library to get IAS report. This demo requires obtaining service provider certificate/ID from Intel.
252 lines
7.6 KiB
C++
252 lines
7.6 KiB
C++
#include <fstream>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "sofaenclave/common/error.h"
|
|
#include "sofaenclave/common/log.h"
|
|
#include "sofaenclave/ra_json.h"
|
|
|
|
namespace sofaenclave {
|
|
namespace occlum {
|
|
|
|
static SofaeErrorCode FsReadString(const std::string& filename,
|
|
std::string* str) {
|
|
std::ifstream ifs(filename, std::ios::binary | std::ios::in);
|
|
if (!ifs) {
|
|
SOFAE_LOG_ERROR("Fail to open file \"%s\"\n", filename.c_str());
|
|
return SOFAE_ERROR_FILE_OPEN;
|
|
}
|
|
|
|
ifs.seekg(0, std::ios::end);
|
|
int length = ifs.tellg();
|
|
ifs.seekg(0, std::ios::beg);
|
|
|
|
std::vector<char> buf(length);
|
|
ifs.read(buf.data(), length);
|
|
if (ifs.fail()) {
|
|
SOFAE_LOG_ERROR("Fail to read file \"%s\"\n", filename.c_str());
|
|
return SOFAE_ERROR_FILE_READ;
|
|
}
|
|
|
|
str->assign(buf.data(), length);
|
|
return SOFAE_SUCCESS;
|
|
}
|
|
|
|
static bool FsFileExists(const std::string& filename) {
|
|
std::ifstream ifs(filename, std::ios::binary | std::ios::in);
|
|
return ifs.good();
|
|
}
|
|
|
|
JsonConfig* JsonConfig::GetInstance() {
|
|
static JsonConfig instance;
|
|
return &instance;
|
|
}
|
|
|
|
template <typename T>
|
|
bool JsonConfig::CheckString(const T& conf, const char* name) {
|
|
if (!conf.HasMember(name) || !conf[name].IsString()) {
|
|
SOFAE_LOG_ERROR("%s is missed or not string in config file", name);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
bool JsonConfig::CheckArray(const T& conf, const char* name) {
|
|
if (!conf.HasMember(name) || !conf[name].IsArray()) {
|
|
SOFAE_LOG_ERROR("%s is missed or not array in config file", name);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
bool JsonConfig::CheckInt(const T& conf, const char* name) {
|
|
if (!conf.HasMember(name) || !conf[name].IsInt()) {
|
|
SOFAE_LOG_ERROR("%s is missed or not integer in config file", name);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
bool JsonConfig::CheckObj(const T& conf, const char* name) {
|
|
if (!conf.HasMember(name) || !conf[name].IsObject()) {
|
|
SOFAE_LOG_ERROR("%s is missed or not object in config file", name);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
std::string JsonConfig::GetStr(const T& conf, const char* name,
|
|
const std::string& default_val) {
|
|
if (CheckString(conf, name)) {
|
|
std::string value = conf[name].GetString();
|
|
SOFAE_LOG_DEBUG("%s=%s", name, value.c_str());
|
|
return value;
|
|
} else {
|
|
SOFAE_LOG_DEBUG("Not string type, %s=%s[default]", name, default_val);
|
|
return default_val;
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
SofaeErrorCode JsonConfig::GetStrArray(const T& conf, const char* name,
|
|
std::vector<std::string>* values) {
|
|
if (CheckArray(conf, name)) {
|
|
const rapidjson::Value& val_array = conf[name];
|
|
size_t count = val_array.Size();
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (val_array[i].IsString()) {
|
|
std::string val_str = val_array[i].GetString();
|
|
SOFAE_LOG_DEBUG("%s[%ld]=%s", name, i, val_str.c_str());
|
|
values->push_back(val_str);
|
|
} else {
|
|
SOFAE_LOG_ERROR("Invalid string type in Array");
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
}
|
|
} else {
|
|
SOFAE_LOG_DEBUG("Invalid Array type");
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
return SOFAE_SUCCESS;
|
|
}
|
|
|
|
template <typename T>
|
|
SofaeErrorCode JsonConfig::GetInt(const T& conf, const char* name, int* value) {
|
|
if (!CheckInt(conf, name)) {
|
|
SOFAE_LOG_ERROR("Not integer type: %s", name);
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
|
|
*value = conf[name].GetInt();
|
|
SOFAE_LOG_DEBUG("%s=%d", name, *value);
|
|
return SOFAE_SUCCESS;
|
|
}
|
|
|
|
std::string JsonConfig::GetConfigFilename(const std::string& filename) {
|
|
// First priority, the absolute path filename or file in current directory
|
|
if (FsFileExists(filename)) {
|
|
SOFAE_LOG_DEBUG("Configuration file: %s", filename.c_str());
|
|
return filename;
|
|
}
|
|
|
|
// Finally, try to find configuration file in /etc directory
|
|
std::string etcpath = "/etc/";
|
|
etcpath += filename;
|
|
if (FsFileExists(etcpath)) {
|
|
SOFAE_LOG_DEBUG("Configuration file: %s", etcpath.c_str());
|
|
return etcpath;
|
|
}
|
|
|
|
// If cannot find configuration file, return empty string
|
|
SOFAE_LOG_ERROR("Cannot find configuration file: %s", filename.c_str());
|
|
return "";
|
|
}
|
|
|
|
SofaeErrorCode JsonConfig::LoadConfiguration(const std::string& filename) {
|
|
if (filename.empty()) {
|
|
SOFAE_LOG_ERROR("Empty configuration file name");
|
|
return SOFAE_ERROR_CONF_NOTEXIST;
|
|
}
|
|
|
|
std::string config_file = GetConfigFilename(filename);
|
|
if (config_file.empty()) {
|
|
SOFAE_LOG_ERROR("Fail to find configuration file");
|
|
return SOFAE_ERROR_CONF_NOTEXIST;
|
|
}
|
|
|
|
std::string config_str;
|
|
if (FsReadString(config_file, &config_str) != SOFAE_SUCCESS) {
|
|
SOFAE_LOG_ERROR("Fail to read configuration file");
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
|
|
SofaeJsonDocPtr doc(new rapidjson::Document);
|
|
if (doc.get()->Parse(config_str.data()).HasParseError()) {
|
|
SOFAE_LOG_ERROR("Fail to parse json configration file");
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
|
|
cfgs_.emplace(filename, doc);
|
|
SOFAE_LOG_DEBUG("Load configuration file %s successfully", filename.c_str());
|
|
return SOFAE_SUCCESS;
|
|
}
|
|
|
|
std::string JsonConfig::ConfGetStr(const std::string& conf_file,
|
|
const char* name,
|
|
const std::string& default_val) {
|
|
SOFAE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str());
|
|
|
|
if (cfgs_.find(conf_file) == cfgs_.end()) {
|
|
if (LoadConfiguration(conf_file) != SOFAE_SUCCESS) {
|
|
SOFAE_LOG_DEBUG("Load config failed, %s=%s[default]", name, default_val);
|
|
return default_val;
|
|
}
|
|
}
|
|
|
|
return GetStr(*cfgs_[conf_file].get(), name, default_val);
|
|
}
|
|
|
|
SofaeErrorCode JsonConfig::ConfGetStrArray(const std::string& conf_file,
|
|
const char* name,
|
|
std::vector<std::string>* values) {
|
|
SOFAE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str());
|
|
|
|
if (cfgs_.find(conf_file) == cfgs_.end()) {
|
|
if (LoadConfiguration(conf_file) != SOFAE_SUCCESS) {
|
|
SOFAE_LOG_DEBUG("Fail to load configuration file");
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
}
|
|
|
|
return GetStrArray(*cfgs_[conf_file].get(), name, values);
|
|
}
|
|
|
|
SofaeErrorCode JsonConfig::ConfGetInt(const std::string& conf_file,
|
|
const char* name, int* value) {
|
|
SOFAE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str());
|
|
|
|
if (cfgs_.find(conf_file) == cfgs_.end()) {
|
|
if (LoadConfiguration(conf_file) != SOFAE_SUCCESS) {
|
|
SOFAE_LOG_ERROR("Fail to load configuration file");
|
|
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
|
}
|
|
}
|
|
|
|
return GetInt(*cfgs_[conf_file].get(), name, value);
|
|
}
|
|
|
|
} // namespace occlum
|
|
} // namespace sofaenclave
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
std::string SofaeConfGetStr(const std::string& conf_file, const char* name,
|
|
const std::string& default_val) {
|
|
return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetStr(
|
|
conf_file, name, default_val);
|
|
}
|
|
|
|
SofaeErrorCode SofaeConfGetStrArray(const std::string& conf_file,
|
|
const char* name,
|
|
std::vector<std::string>* values) {
|
|
return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetStrArray(
|
|
conf_file, name, values);
|
|
}
|
|
|
|
SofaeErrorCode SofaeConfGetInt(const std::string& conf_file, const char* name,
|
|
int* value) {
|
|
return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetInt(
|
|
conf_file, name, value);
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|