IcingaDB: introduce a new environment ID derived from the CA public key

In order to avoid changes to the environment ID, it is now no longer derived
from the Environment constant but instead from the public key of the CA
certificate. This ensures that it is different between clusters by default, so
no additional changes have to be done to allow two clusters to use Icinga DB to
write into the same database.

To prevent the ID from changing when the CA certificate is replaced, it is also
persisted into the file /var/lib/icinga2/icingadb.env, so if that file exists,
it takes precedence over the CA certificate.
This commit is contained in:
Julian Brost 2021-09-21 12:56:20 +02:00 committed by Noah Hilverling
parent 1dcba7d127
commit 42fc3cdcfc
4 changed files with 69 additions and 44 deletions

View File

@ -612,7 +612,6 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
} }
CustomVarObject::Ptr customVarObject = dynamic_pointer_cast<CustomVarObject>(object); CustomVarObject::Ptr customVarObject = dynamic_pointer_cast<CustomVarObject>(object);
auto env (GetEnvironment());
if (customVarObject) { if (customVarObject) {
auto vars(SerializeVars(customVarObject)); auto vars(SerializeVars(customVarObject));
@ -635,7 +634,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
} }
} }
String id = HashValue(new Array(Prepend(env, Prepend(kv.first, GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(kv.first, GetObjectIdentifiersWithoutEnv(object)))));
typeCvs.emplace_back(id); typeCvs.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{objectKeyName, objectKey}, {"environment_id", m_EnvironmentId}, {"customvar_id", kv.first}}); Dictionary::Ptr data = new Dictionary({{objectKeyName, objectKey}, {"environment_id", m_EnvironmentId}, {"customvar_id", kv.first}});
@ -657,7 +656,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
if (!actionUrl.IsEmpty()) { if (!actionUrl.IsEmpty()) {
auto& actionUrls (hMSets[m_PrefixConfigObject + "action:url"]); auto& actionUrls (hMSets[m_PrefixConfigObject + "action:url"]);
auto id (HashValue(new Array({env, actionUrl}))); auto id (HashValue(new Array({m_EnvironmentId, actionUrl})));
if (runtimeUpdate || m_DumpedGlobals.ActionUrl.IsNew(id)) { if (runtimeUpdate || m_DumpedGlobals.ActionUrl.IsNew(id)) {
actionUrls.emplace_back(std::move(id)); actionUrls.emplace_back(std::move(id));
@ -672,7 +671,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
if (!notesUrl.IsEmpty()) { if (!notesUrl.IsEmpty()) {
auto& notesUrls (hMSets[m_PrefixConfigObject + "notes:url"]); auto& notesUrls (hMSets[m_PrefixConfigObject + "notes:url"]);
auto id (HashValue(new Array({env, notesUrl}))); auto id (HashValue(new Array({m_EnvironmentId, notesUrl})));
if (runtimeUpdate || m_DumpedGlobals.NotesUrl.IsNew(id)) { if (runtimeUpdate || m_DumpedGlobals.NotesUrl.IsNew(id)) {
notesUrls.emplace_back(std::move(id)); notesUrls.emplace_back(std::move(id));
@ -687,7 +686,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
if (!iconImage.IsEmpty()) { if (!iconImage.IsEmpty()) {
auto& iconImages (hMSets[m_PrefixConfigObject + "icon:image"]); auto& iconImages (hMSets[m_PrefixConfigObject + "icon:image"]);
auto id (HashValue(new Array({env, iconImage}))); auto id (HashValue(new Array({m_EnvironmentId, iconImage})));
if (runtimeUpdate || m_DumpedGlobals.IconImage.IsNew(id)) { if (runtimeUpdate || m_DumpedGlobals.IconImage.IsNew(id)) {
iconImages.emplace_back(std::move(id)); iconImages.emplace_back(std::move(id));
@ -725,7 +724,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
for (auto& group : groups) { for (auto& group : groups) {
auto groupObj ((*getGroup)(group)); auto groupObj ((*getGroup)(group));
String groupId = GetObjectIdentifier(groupObj); String groupId = GetObjectIdentifier(groupObj);
String id = HashValue(new Array(Prepend(env, Prepend(GetObjectIdentifiersWithoutEnv(groupObj), GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(GetObjectIdentifiersWithoutEnv(groupObj), GetObjectIdentifiersWithoutEnv(object)))));
members.emplace_back(id); members.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{objectKeyName, objectKey}, {"environment_id", m_EnvironmentId}, {typeName + "group_id", groupId}}); Dictionary::Ptr data = new Dictionary({{objectKeyName, objectKey}, {"environment_id", m_EnvironmentId}, {typeName + "group_id", groupId}});
members.emplace_back(JsonEncode(data)); members.emplace_back(JsonEncode(data));
@ -753,10 +752,10 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
rangeIds->Reserve(ranges->GetLength()); rangeIds->Reserve(ranges->GetLength());
for (auto& kv : ranges) { for (auto& kv : ranges) {
String rangeId = HashValue(new Array({env, kv.first, kv.second})); String rangeId = HashValue(new Array({m_EnvironmentId, kv.first, kv.second}));
rangeIds->Add(rangeId); rangeIds->Add(rangeId);
String id = HashValue(new Array(Prepend(env, Prepend(kv.first, Prepend(kv.second, GetObjectIdentifiersWithoutEnv(object)))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(kv.first, Prepend(kv.second, GetObjectIdentifiersWithoutEnv(object))))));
typeRanges.emplace_back(id); typeRanges.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{"environment_id", m_EnvironmentId}, {"timeperiod_id", objectKey}, {"range_key", kv.first}, {"range_value", kv.second}}); Dictionary::Ptr data = new Dictionary({{"environment_id", m_EnvironmentId}, {"timeperiod_id", objectKey}, {"range_key", kv.first}, {"range_value", kv.second}});
typeRanges.emplace_back(JsonEncode(data)); typeRanges.emplace_back(JsonEncode(data));
@ -786,7 +785,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
String includeId = GetObjectIdentifier(includeTp); String includeId = GetObjectIdentifier(includeTp);
includeChecksums->Add(includeId); includeChecksums->Add(includeId);
String id = HashValue(new Array(Prepend(env, Prepend(GetObjectIdentifiersWithoutEnv(includeTp), GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(GetObjectIdentifiersWithoutEnv(includeTp), GetObjectIdentifiersWithoutEnv(object)))));
includs.emplace_back(id); includs.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{"environment_id", m_EnvironmentId}, {"timeperiod_id", objectKey}, {"include_id", includeId}}); Dictionary::Ptr data = new Dictionary({{"environment_id", m_EnvironmentId}, {"timeperiod_id", objectKey}, {"include_id", includeId}});
includs.emplace_back(JsonEncode(data)); includs.emplace_back(JsonEncode(data));
@ -816,7 +815,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
String excludeId = GetObjectIdentifier(excludeTp); String excludeId = GetObjectIdentifier(excludeTp);
excludeChecksums->Add(excludeId); excludeChecksums->Add(excludeId);
String id = HashValue(new Array(Prepend(env, Prepend(GetObjectIdentifiersWithoutEnv(excludeTp), GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(GetObjectIdentifiersWithoutEnv(excludeTp), GetObjectIdentifiersWithoutEnv(object)))));
excluds.emplace_back(id); excluds.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{"environment_id", m_EnvironmentId}, {"timeperiod_id", objectKey}, {"exclude_id", excludeId}}); Dictionary::Ptr data = new Dictionary({{"environment_id", m_EnvironmentId}, {"timeperiod_id", objectKey}, {"exclude_id", excludeId}});
excluds.emplace_back(JsonEncode(data)); excluds.emplace_back(JsonEncode(data));
@ -849,7 +848,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
for (auto& group : groups) { for (auto& group : groups) {
auto groupObj ((*getGroup)(group)); auto groupObj ((*getGroup)(group));
String groupId = GetObjectIdentifier(groupObj); String groupId = GetObjectIdentifier(groupObj);
String id = HashValue(new Array(Prepend(env, Prepend(GetObjectIdentifiersWithoutEnv(groupObj), GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(GetObjectIdentifiersWithoutEnv(groupObj), GetObjectIdentifiersWithoutEnv(object)))));
members.emplace_back(id); members.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{"user_id", objectKey}, {"environment_id", m_EnvironmentId}, {"usergroup_id", groupId}}); Dictionary::Ptr data = new Dictionary({{"user_id", objectKey}, {"environment_id", m_EnvironmentId}, {"usergroup_id", groupId}});
members.emplace_back(JsonEncode(data)); members.emplace_back(JsonEncode(data));
@ -884,7 +883,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
for (auto& user : users) { for (auto& user : users) {
String userId = GetObjectIdentifier(user); String userId = GetObjectIdentifier(user);
String id = HashValue(new Array(Prepend(env, Prepend(GetObjectIdentifiersWithoutEnv(user), GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(GetObjectIdentifiersWithoutEnv(user), GetObjectIdentifiersWithoutEnv(object)))));
usrs.emplace_back(id); usrs.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{"notification_id", objectKey}, {"environment_id", m_EnvironmentId}, {"user_id", userId}}); Dictionary::Ptr data = new Dictionary({{"notification_id", objectKey}, {"environment_id", m_EnvironmentId}, {"user_id", userId}});
usrs.emplace_back(JsonEncode(data)); usrs.emplace_back(JsonEncode(data));
@ -907,7 +906,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
auto groupMembers = usergroup->GetMembers(); auto groupMembers = usergroup->GetMembers();
std::copy(groupMembers.begin(), groupMembers.end(), std::inserter(allUsers, allUsers.begin())); std::copy(groupMembers.begin(), groupMembers.end(), std::inserter(allUsers, allUsers.begin()));
String id = HashValue(new Array(Prepend(env, Prepend("usergroup", Prepend(GetObjectIdentifiersWithoutEnv(usergroup), GetObjectIdentifiersWithoutEnv(object)))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend("usergroup", Prepend(GetObjectIdentifiersWithoutEnv(usergroup), GetObjectIdentifiersWithoutEnv(object))))));
groups.emplace_back(id); groups.emplace_back(id);
Dictionary::Ptr groupData = new Dictionary({{"notification_id", objectKey}, {"environment_id", m_EnvironmentId}, {"usergroup_id", usergroupId}}); Dictionary::Ptr groupData = new Dictionary({{"notification_id", objectKey}, {"environment_id", m_EnvironmentId}, {"usergroup_id", usergroupId}});
groups.emplace_back(JsonEncode(groupData)); groups.emplace_back(JsonEncode(groupData));
@ -926,7 +925,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
for (auto& user : allUsers) { for (auto& user : allUsers) {
String userId = GetObjectIdentifier(user); String userId = GetObjectIdentifier(user);
String id = HashValue(new Array(Prepend(env, Prepend("user", Prepend(GetObjectIdentifiersWithoutEnv(user), GetObjectIdentifiersWithoutEnv(object)))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend("user", Prepend(GetObjectIdentifiersWithoutEnv(user), GetObjectIdentifiersWithoutEnv(object))))));
notificationRecipients.emplace_back(id); notificationRecipients.emplace_back(id);
Dictionary::Ptr data = new Dictionary({{"notification_id", objectKey}, {"environment_id", m_EnvironmentId}, {"user_id", userId}}); Dictionary::Ptr data = new Dictionary({{"notification_id", objectKey}, {"environment_id", m_EnvironmentId}, {"user_id", userId}});
notificationRecipients.emplace_back(JsonEncode(data)); notificationRecipients.emplace_back(JsonEncode(data));
@ -980,7 +979,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
values->Set("argument_key", kv.first); values->Set("argument_key", kv.first);
values->Set("environment_id", m_EnvironmentId); values->Set("environment_id", m_EnvironmentId);
String id = HashValue(new Array(Prepend(env, Prepend(kv.first, GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(kv.first, GetObjectIdentifiersWithoutEnv(object)))));
typeArgs.emplace_back(id); typeArgs.emplace_back(id);
typeArgs.emplace_back(JsonEncode(values)); typeArgs.emplace_back(JsonEncode(values));
@ -1029,7 +1028,7 @@ void IcingaDB::InsertObjectDependencies(const ConfigObject::Ptr& object, const S
values->Set("envvar_key", kv.first); values->Set("envvar_key", kv.first);
values->Set("environment_id", m_EnvironmentId); values->Set("environment_id", m_EnvironmentId);
String id = HashValue(new Array(Prepend(env, Prepend(kv.first, GetObjectIdentifiersWithoutEnv(object))))); String id = HashValue(new Array(Prepend(m_EnvironmentId, Prepend(kv.first, GetObjectIdentifiersWithoutEnv(object)))));
typeVars.emplace_back(id); typeVars.emplace_back(id);
typeVars.emplace_back(JsonEncode(values)); typeVars.emplace_back(JsonEncode(values));
@ -1219,11 +1218,11 @@ bool IcingaDB::PrepareObject(const ConfigObject::Ptr& object, Dictionary::Ptr& a
String notesUrl = checkable->GetNotesUrl(); String notesUrl = checkable->GetNotesUrl();
String iconImage = checkable->GetIconImage(); String iconImage = checkable->GetIconImage();
if (!actionUrl.IsEmpty()) if (!actionUrl.IsEmpty())
attributes->Set("action_url_id", HashValue(new Array({GetEnvironment(), actionUrl}))); attributes->Set("action_url_id", HashValue(new Array({m_EnvironmentId, actionUrl})));
if (!notesUrl.IsEmpty()) if (!notesUrl.IsEmpty())
attributes->Set("notes_url_id", HashValue(new Array({GetEnvironment(), notesUrl}))); attributes->Set("notes_url_id", HashValue(new Array({m_EnvironmentId, notesUrl})));
if (!iconImage.IsEmpty()) if (!iconImage.IsEmpty())
attributes->Set("icon_image_id", HashValue(new Array({GetEnvironment(), iconImage}))); attributes->Set("icon_image_id", HashValue(new Array({m_EnvironmentId, iconImage})));
Host::Ptr host; Host::Ptr host;
@ -1556,7 +1555,7 @@ void IcingaDB::SendStateChange(const ConfigObject::Ptr& object, const CheckResul
auto eventTime (cr->GetExecutionEnd()); auto eventTime (cr->GetExecutionEnd());
auto eventTs (TimestampToMilliseconds(eventTime)); auto eventTs (TimestampToMilliseconds(eventTime));
Array::Ptr rawId = new Array(Prepend(GetEnvironment(), GetObjectIdentifiersWithoutEnv(object))); Array::Ptr rawId = new Array(Prepend(m_EnvironmentId, GetObjectIdentifiersWithoutEnv(object)));
rawId->Add(eventTs); rawId->Add(eventTs);
std::vector<String> xAdd ({ std::vector<String> xAdd ({
@ -1636,7 +1635,7 @@ void IcingaDB::SendSentNotification(
auto usersAmount (users.size()); auto usersAmount (users.size());
auto sendTs (TimestampToMilliseconds(sendTime)); auto sendTs (TimestampToMilliseconds(sendTime));
Array::Ptr rawId = new Array(Prepend(GetEnvironment(), GetObjectIdentifiersWithoutEnv(notification))); Array::Ptr rawId = new Array(Prepend(m_EnvironmentId, GetObjectIdentifiersWithoutEnv(notification)));
rawId->Add(GetNotificationTypeByEnum(type)); rawId->Add(GetNotificationTypeByEnum(type));
rawId->Add(sendTs); rawId->Add(sendTs);
@ -2043,7 +2042,7 @@ void IcingaDB::SendFlappingChange(const Checkable::Ptr& checkable, double change
xAdd.emplace_back("event_id"); xAdd.emplace_back("event_id");
xAdd.emplace_back(CalcEventID(checkable->IsFlapping() ? "flapping_start" : "flapping_end", checkable, startTime)); xAdd.emplace_back(CalcEventID(checkable->IsFlapping() ? "flapping_start" : "flapping_end", checkable, startTime));
xAdd.emplace_back("id"); xAdd.emplace_back("id");
xAdd.emplace_back(HashValue(new Array({GetEnvironment(), checkable->GetName(), startTime}))); xAdd.emplace_back(HashValue(new Array({m_EnvironmentId, checkable->GetName(), startTime})));
m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History); m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History);
} }
@ -2124,7 +2123,7 @@ void IcingaDB::SendAcknowledgementSet(const Checkable::Ptr& checkable, const Str
xAdd.emplace_back("event_id"); xAdd.emplace_back("event_id");
xAdd.emplace_back(CalcEventID("ack_set", checkable, setTime)); xAdd.emplace_back(CalcEventID("ack_set", checkable, setTime));
xAdd.emplace_back("id"); xAdd.emplace_back("id");
xAdd.emplace_back(HashValue(new Array({GetEnvironment(), checkable->GetName(), setTime}))); xAdd.emplace_back(HashValue(new Array({m_EnvironmentId, checkable->GetName(), setTime})));
m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History); m_Rcon->FireAndForgetQuery(std::move(xAdd), Prio::History);
} }
@ -2170,7 +2169,7 @@ void IcingaDB::SendAcknowledgementCleared(const Checkable::Ptr& checkable, const
xAdd.emplace_back("event_id"); xAdd.emplace_back("event_id");
xAdd.emplace_back(CalcEventID("ack_clear", checkable, setTime)); xAdd.emplace_back(CalcEventID("ack_clear", checkable, setTime));
xAdd.emplace_back("id"); xAdd.emplace_back("id");
xAdd.emplace_back(HashValue(new Array({GetEnvironment(), checkable->GetName(), setTime}))); xAdd.emplace_back(HashValue(new Array({m_EnvironmentId, checkable->GetName(), setTime})));
if (!removedBy.IsEmpty()) { if (!removedBy.IsEmpty()) {
xAdd.emplace_back("cleared_by"); xAdd.emplace_back("cleared_by");

View File

@ -60,11 +60,6 @@ String IcingaDB::FormatCommandLine(const Value& commandLine)
return result; return result;
} }
String IcingaDB::GetEnvironment()
{
return ConfigType::GetObjectsByType<IcingaApplication>()[0]->GetEnvironment();
}
ArrayData IcingaDB::GetObjectIdentifiersWithoutEnv(const ConfigObject::Ptr& object) ArrayData IcingaDB::GetObjectIdentifiersWithoutEnv(const ConfigObject::Ptr& object)
{ {
Type::Ptr type = object->GetReflectionType(); Type::Ptr type = object->GetReflectionType();
@ -77,7 +72,7 @@ ArrayData IcingaDB::GetObjectIdentifiersWithoutEnv(const ConfigObject::Ptr& obje
String IcingaDB::GetObjectIdentifier(const ConfigObject::Ptr& object) String IcingaDB::GetObjectIdentifier(const ConfigObject::Ptr& object)
{ {
return HashValue(new Array(Prepend(GetEnvironment(), GetObjectIdentifiersWithoutEnv(object)))); return HashValue(new Array(Prepend(m_EnvironmentId, GetObjectIdentifiersWithoutEnv(object))));
} }
/** /**
@ -88,7 +83,7 @@ String IcingaDB::GetObjectIdentifier(const ConfigObject::Ptr& object)
String IcingaDB::CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime, NotificationType nt) String IcingaDB::CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime, NotificationType nt)
{ {
Array::Ptr rawId = new Array(GetObjectIdentifiersWithoutEnv(object)); Array::Ptr rawId = new Array(GetObjectIdentifiersWithoutEnv(object));
rawId->Insert(0, GetEnvironment()); rawId->Insert(0, m_EnvironmentId);
rawId->Insert(1, eventType); rawId->Insert(1, eventType);
if (nt) { if (nt) {
@ -118,7 +113,7 @@ static const std::set<String> metadataWhitelist ({"package", "source_location",
* *
* return { * return {
* SHA1(PackObject([ * SHA1(PackObject([
* Environment, * EnvironmentId,
* "disks", * "disks",
* { * {
* "disk": {}, * "disk": {},
@ -127,7 +122,7 @@ static const std::set<String> metadataWhitelist ({"package", "source_location",
* } * }
* } * }
* ])): { * ])): {
* "envId": SHA1(Environment), * "environment_id": EnvironmentId,
* "name_checksum": SHA1("disks"), * "name_checksum": SHA1("disks"),
* "name": "disks", * "name": "disks",
* "value": { * "value": {
@ -151,16 +146,14 @@ Dictionary::Ptr IcingaDB::SerializeVars(const CustomVarObject::Ptr& object)
return nullptr; return nullptr;
Dictionary::Ptr res = new Dictionary(); Dictionary::Ptr res = new Dictionary();
auto env (GetEnvironment());
auto envChecksum (SHA1(env));
ObjectLock olock(vars); ObjectLock olock(vars);
for (auto& kv : vars) { for (auto& kv : vars) {
res->Set( res->Set(
SHA1(PackObject((Array::Ptr)new Array({env, kv.first, kv.second}))), SHA1(PackObject((Array::Ptr)new Array({m_EnvironmentId, kv.first, kv.second}))),
(Dictionary::Ptr)new Dictionary({ (Dictionary::Ptr)new Dictionary({
{"environment_id", envChecksum}, {"environment_id", m_EnvironmentId},
{"name_checksum", SHA1(kv.first)}, {"name_checksum", SHA1(kv.first)},
{"name", kv.first}, {"name", kv.first},
{"value", JsonEncode(kv.second)}, {"value", JsonEncode(kv.second)},

View File

@ -3,11 +3,16 @@
#include "icingadb/icingadb.hpp" #include "icingadb/icingadb.hpp"
#include "icingadb/icingadb-ti.cpp" #include "icingadb/icingadb-ti.cpp"
#include "icingadb/redisconnection.hpp" #include "icingadb/redisconnection.hpp"
#include "remote/apilistener.hpp"
#include "remote/eventqueue.hpp" #include "remote/eventqueue.hpp"
#include "base/configuration.hpp"
#include "base/json.hpp" #include "base/json.hpp"
#include "base/tlsutility.hpp"
#include "base/utility.hpp"
#include "icinga/checkable.hpp" #include "icinga/checkable.hpp"
#include "icinga/host.hpp" #include "icinga/host.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <fstream>
#include <memory> #include <memory>
#include <utility> #include <utility>
@ -18,7 +23,7 @@ using namespace icinga;
using Prio = RedisConnection::QueryPriority; using Prio = RedisConnection::QueryPriority;
String IcingaDB::m_EnvironmentId; String IcingaDB::m_EnvironmentId;
boost::once_flag IcingaDB::m_EnvironmentIdOnce = BOOST_ONCE_INIT; std::once_flag IcingaDB::m_EnvironmentIdOnce;
REGISTER_TYPE(IcingaDB); REGISTER_TYPE(IcingaDB);
@ -52,9 +57,39 @@ void IcingaDB::Start(bool runtimeCreated)
{ {
ObjectImpl<IcingaDB>::Start(runtimeCreated); ObjectImpl<IcingaDB>::Start(runtimeCreated);
boost::call_once([]() { std::call_once(m_EnvironmentIdOnce, []() {
m_EnvironmentId = SHA1(GetEnvironment()); String path = Configuration::DataDir + "/icingadb.env";
}, m_EnvironmentIdOnce);
if (Utility::PathExists(path)) {
m_EnvironmentId = Utility::LoadJsonFile(path);
if (m_EnvironmentId.GetLength() != 2*SHA_DIGEST_LENGTH) {
throw std::runtime_error("Wrong length of stored Icinga DB environment");
}
for (unsigned char c : m_EnvironmentId) {
if (!std::isxdigit(c)) {
throw std::runtime_error("Stored Icinga DB environment is not a hex string");
}
}
} else {
std::shared_ptr<X509> cert = GetX509Certificate(ApiListener::GetDefaultCaPath());
unsigned int n;
unsigned char digest[EVP_MAX_MD_SIZE];
if (X509_pubkey_digest(cert.get(), EVP_sha1(), digest, &n) != 1) {
BOOST_THROW_EXCEPTION(openssl_error()
<< boost::errinfo_api_function("X509_pubkey_digest")
<< errinfo_openssl_error(ERR_peek_error()));
}
m_EnvironmentId = BinaryToHex(digest, n);
Utility::SaveJsonFile(path, 0600, m_EnvironmentId);
}
m_EnvironmentId = m_EnvironmentId.ToLower();
});
Log(LogInformation, "IcingaDB") Log(LogInformation, "IcingaDB")
<< "'" << GetName() << "' started."; << "'" << GetName() << "' started.";

View File

@ -12,7 +12,6 @@
#include "icinga/service.hpp" #include "icinga/service.hpp"
#include "icinga/downtime.hpp" #include "icinga/downtime.hpp"
#include "remote/messageorigin.hpp" #include "remote/messageorigin.hpp"
#include <boost/thread/once.hpp>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
@ -108,7 +107,6 @@ private:
static ArrayData GetObjectIdentifiersWithoutEnv(const ConfigObject::Ptr& object); static ArrayData GetObjectIdentifiersWithoutEnv(const ConfigObject::Ptr& object);
static String GetObjectIdentifier(const ConfigObject::Ptr& object); static String GetObjectIdentifier(const ConfigObject::Ptr& object);
static String CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime = 0, NotificationType nt = NotificationType(0)); static String CalcEventID(const char* eventType, const ConfigObject::Ptr& object, double eventTime = 0, NotificationType nt = NotificationType(0));
static String GetEnvironment();
static Dictionary::Ptr SerializeVars(const CustomVarObject::Ptr& object); static Dictionary::Ptr SerializeVars(const CustomVarObject::Ptr& object);
static const char* GetNotificationTypeByEnum(NotificationType type); static const char* GetNotificationTypeByEnum(NotificationType type);
@ -180,7 +178,7 @@ private:
} m_DumpedGlobals; } m_DumpedGlobals;
static String m_EnvironmentId; static String m_EnvironmentId;
static boost::once_flag m_EnvironmentIdOnce; static std::once_flag m_EnvironmentIdOnce;
}; };
} }