mirror of https://github.com/Icinga/icinga2.git
parent
6e70e2ddf0
commit
0b466aabc0
|
@ -591,6 +591,46 @@ String PBKDF2_SHA1(const String& password, const String& salt, int iterations)
|
|||
return output;
|
||||
}
|
||||
|
||||
String SHA1(const String& s, bool binary)
|
||||
{
|
||||
char errbuf[120];
|
||||
SHA_CTX context;
|
||||
unsigned char digest[SHA_DIGEST_LENGTH];
|
||||
|
||||
if (!SHA1_Init(&context)) {
|
||||
Log(LogCritical, "SSL")
|
||||
<< "Error on SHA Init: " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\"";
|
||||
BOOST_THROW_EXCEPTION(openssl_error()
|
||||
<< boost::errinfo_api_function("SHA1_Init")
|
||||
<< errinfo_openssl_error(ERR_peek_error()));
|
||||
}
|
||||
|
||||
if (!SHA1_Update(&context, (unsigned char*)s.CStr(), s.GetLength())) {
|
||||
Log(LogCritical, "SSL")
|
||||
<< "Error on SHA Update: " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\"";
|
||||
BOOST_THROW_EXCEPTION(openssl_error()
|
||||
<< boost::errinfo_api_function("SHA1_Update")
|
||||
<< errinfo_openssl_error(ERR_peek_error()));
|
||||
}
|
||||
|
||||
if (!SHA1_Final(digest, &context)) {
|
||||
Log(LogCritical, "SSL")
|
||||
<< "Error on SHA Final: " << ERR_peek_error() << ", \"" << ERR_error_string(ERR_peek_error(), errbuf) << "\"";
|
||||
BOOST_THROW_EXCEPTION(openssl_error()
|
||||
<< boost::errinfo_api_function("SHA1_Final")
|
||||
<< errinfo_openssl_error(ERR_peek_error()));
|
||||
}
|
||||
|
||||
if (binary)
|
||||
return String(reinterpret_cast<const char*>(digest));
|
||||
|
||||
char output[SHA_DIGEST_LENGTH*2+1];
|
||||
for (int i = 0; i < 20; i++)
|
||||
sprintf(output + 2 * i, "%02x", digest[i]);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
String SHA256(const String& s)
|
||||
{
|
||||
char errbuf[120];
|
||||
|
|
|
@ -50,7 +50,7 @@ String I2_BASE_API GetIcingaCADir(void);
|
|||
String I2_BASE_API CertificateToString(const boost::shared_ptr<X509>& cert);
|
||||
boost::shared_ptr<X509> I2_BASE_API CreateCertIcingaCA(EVP_PKEY *pubkey, X509_NAME *subject);
|
||||
String I2_BASE_API PBKDF2_SHA1(const String& password, const String& salt, int iterations);
|
||||
String I2_BASE_API SHA1(const String& s);
|
||||
String I2_BASE_API SHA1(const String& s, bool binary = false);
|
||||
String I2_BASE_API SHA256(const String& s);
|
||||
String I2_BASE_API RandomString(int length);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
mkclass_target(rediswriter.ti rediswriter.tcpp rediswriter.thpp)
|
||||
|
||||
set(redis_SOURCES
|
||||
rediswriter.cpp rediswriter-config.cpp rediswriter.thpp
|
||||
rediswriter.cpp rediswriter-config.cpp rediswriter-utility.cpp rediswriter.thpp
|
||||
)
|
||||
|
||||
if(ICINGA2_UNITY_BUILD)
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
|
||||
#include "redis/rediswriter.hpp"
|
||||
#include "icinga/customvarobject.hpp"
|
||||
#include "icinga/host.hpp"
|
||||
#include "icinga/service.hpp"
|
||||
#include "base/json.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/serializer.hpp"
|
||||
#include "base/tlsutility.hpp"
|
||||
#include "base/initialize.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
@ -52,12 +55,10 @@ void RedisWriter::ConfigStaticInitialize(void)
|
|||
ConfigObject::OnVersionChanged.connect(boost::bind(&RedisWriter::VersionChangedHandler, _1));
|
||||
}
|
||||
|
||||
//TODO: OnActiveChanged handling.
|
||||
void RedisWriter::UpdateAllConfigObjects(void)
|
||||
{
|
||||
AssertOnWorkQueue();
|
||||
|
||||
//TODO: Just use config types
|
||||
for (const Type::Ptr& type : Type::GetAllTypes()) {
|
||||
if (!ConfigObject::TypeInstance->IsAssignableFrom(type))
|
||||
continue;
|
||||
|
@ -108,25 +109,62 @@ void RedisWriter::SendConfigUpdate(const ConfigObject::Ptr& object, const String
|
|||
//TODO: checksum
|
||||
String objectName = object->GetName();
|
||||
|
||||
redisReply *reply = reinterpret_cast<redisReply *>(redisCommand(m_Context, "HSET icinga:config:%s %s %s", typeName.CStr(), objectName.CStr(), jsonBody.CStr()));
|
||||
redisReply *reply1 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "HSET icinga:config:%s %s %s", typeName.CStr(), objectName.CStr(), jsonBody.CStr()));
|
||||
|
||||
if (!reply) {
|
||||
if (!reply1) {
|
||||
redisFree(m_Context);
|
||||
m_Context = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->type == REDIS_REPLY_STATUS || reply->type == REDIS_REPLY_ERROR) {
|
||||
if (reply1->type == REDIS_REPLY_STATUS || reply1->type == REDIS_REPLY_ERROR) {
|
||||
Log(LogInformation, "RedisWriter")
|
||||
<< "HSET icinga:config:" << typeName << " " << objectName << " " << jsonBody << ": " << reply->str;
|
||||
<< "HSET icinga:config:" << typeName << " " << objectName << " " << jsonBody << ": " << reply1->str;
|
||||
}
|
||||
|
||||
if (reply->type == REDIS_REPLY_ERROR) {
|
||||
freeReplyObject(reply);
|
||||
if (reply1->type == REDIS_REPLY_ERROR) {
|
||||
freeReplyObject(reply1);
|
||||
return;
|
||||
}
|
||||
|
||||
freeReplyObject(reply);
|
||||
freeReplyObject(reply1);
|
||||
|
||||
|
||||
/* check sums */
|
||||
/* hset icinga:config:Host:checksums localhost { "name_checksum": "...", "properties_checksum": "...", "groups_checksum": "...", "vars_checksum": null } */
|
||||
Dictionary::Ptr checkSum = new Dictionary();
|
||||
|
||||
checkSum->Set("name_checksum", CalculateCheckSumString(object->GetName()));
|
||||
|
||||
if (object->GetReflectionType() == Host::TypeInstance) {
|
||||
Host::Ptr host = static_pointer_cast<Host>(object);
|
||||
checkSum->Set("groups_checksum", CalculateCheckSumGroups(host->GetGroups()));
|
||||
} else if (object->GetReflectionType() == Service::TypeInstance) {
|
||||
Service::Ptr service = static_pointer_cast<Service>(object);
|
||||
checkSum->Set("groups_checksum", CalculateCheckSumGroups(service->GetGroups()));
|
||||
}
|
||||
|
||||
String checkSumBody = JsonEncode(checkSum);
|
||||
|
||||
redisReply *reply2 = reinterpret_cast<redisReply *>(redisCommand(m_Context, "HSET icinga:config:%s:checksum %s %s", typeName.CStr(), objectName.CStr(), checkSumBody.CStr()));
|
||||
|
||||
if (!reply2) {
|
||||
redisFree(m_Context);
|
||||
m_Context = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply2->type == REDIS_REPLY_STATUS || reply2->type == REDIS_REPLY_ERROR) {
|
||||
Log(LogInformation, "RedisWriter")
|
||||
<< "HSET icinga:config:" << typeName << " " << objectName << " " << jsonBody << ": " << reply2->str;
|
||||
}
|
||||
|
||||
if (reply2->type == REDIS_REPLY_ERROR) {
|
||||
freeReplyObject(reply2);
|
||||
return;
|
||||
}
|
||||
|
||||
freeReplyObject(reply2);
|
||||
}
|
||||
|
||||
void RedisWriter::SendStatusUpdate(const ConfigObject::Ptr& object, const String& typeName)
|
||||
|
@ -162,41 +200,6 @@ void RedisWriter::SendStatusUpdate(const ConfigObject::Ptr& object, const String
|
|||
freeReplyObject(reply);
|
||||
}
|
||||
|
||||
Dictionary::Ptr RedisWriter::SerializeObjectAttrs(const Object::Ptr& object, int fieldType)
|
||||
{
|
||||
Type::Ptr type = object->GetReflectionType();
|
||||
|
||||
std::vector<int> fids;
|
||||
|
||||
for (int fid = 0; fid < type->GetFieldCount(); fid++) {
|
||||
fids.push_back(fid);
|
||||
}
|
||||
|
||||
Dictionary::Ptr resultAttrs = new Dictionary();
|
||||
|
||||
for (int& fid : fids) {
|
||||
Field field = type->GetFieldInfo(fid);
|
||||
|
||||
if ((field.Attributes & fieldType) == 0)
|
||||
continue;
|
||||
|
||||
Value val = object->GetField(fid);
|
||||
|
||||
/* hide attributes which shouldn't be user-visible */
|
||||
if (field.Attributes & FANoUserView)
|
||||
continue;
|
||||
|
||||
/* hide internal navigation fields */
|
||||
if (field.Attributes & FANavigation && !(field.Attributes & (FAConfig | FAState)))
|
||||
continue;
|
||||
|
||||
Value sval = Serialize(val);
|
||||
resultAttrs->Set(field.Name, sval);
|
||||
}
|
||||
|
||||
return resultAttrs;
|
||||
}
|
||||
|
||||
void RedisWriter::StateChangedHandler(const ConfigObject::Ptr& object)
|
||||
{
|
||||
Type::Ptr type = object->GetReflectionType();
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/******************************************************************************
|
||||
* Icinga 2 *
|
||||
* Copyright (C) 2012-2017 Icinga Development Team (https://www.icinga.com/) *
|
||||
* *
|
||||
* 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 2 *
|
||||
* 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, write to the Free Software Foundation *
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
******************************************************************************/
|
||||
|
||||
#include "redis/rediswriter.hpp"
|
||||
#include "icinga/customvarobject.hpp"
|
||||
#include "base/json.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include "base/serializer.hpp"
|
||||
#include "base/tlsutility.hpp"
|
||||
#include "base/initialize.hpp"
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
String RedisWriter::FormatCheckSumBinary(const String& str)
|
||||
{
|
||||
char output[20*2+1];
|
||||
for (int i = 0; i < 20; i++)
|
||||
sprintf(output + 2 * i, "%02x", str[i]);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
String RedisWriter::CalculateCheckSumString(const String& str)
|
||||
{
|
||||
return SHA1(str, true);
|
||||
}
|
||||
|
||||
String RedisWriter::CalculateCheckSumGroups(const Array::Ptr& groups)
|
||||
{
|
||||
String output;
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (const String& group : groups) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
output += ";";
|
||||
|
||||
output += SHA1(group, true); //binary checksum required here
|
||||
}
|
||||
|
||||
return SHA1(output, false);
|
||||
}
|
||||
|
||||
String RedisWriter::CalculateCheckSumAttrs(const Dictionary::Ptr& attrs)
|
||||
{
|
||||
String output;
|
||||
|
||||
//TODO: Implement
|
||||
for (const Dictionary::Pair& kv: attrs) {
|
||||
if (kv.second.IsNumber()) {
|
||||
//use a precision of 6 for floating point numbers
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
Dictionary::Ptr RedisWriter::SerializeObjectAttrs(const Object::Ptr& object, int fieldType)
|
||||
{
|
||||
Type::Ptr type = object->GetReflectionType();
|
||||
|
||||
std::vector<int> fids;
|
||||
|
||||
for (int fid = 0; fid < type->GetFieldCount(); fid++) {
|
||||
fids.push_back(fid);
|
||||
}
|
||||
|
||||
Dictionary::Ptr resultAttrs = new Dictionary();
|
||||
|
||||
for (int& fid : fids) {
|
||||
Field field = type->GetFieldInfo(fid);
|
||||
|
||||
if ((field.Attributes & fieldType) == 0)
|
||||
continue;
|
||||
|
||||
Value val = object->GetField(fid);
|
||||
|
||||
/* hide attributes which shouldn't be user-visible */
|
||||
if (field.Attributes & FANoUserView)
|
||||
continue;
|
||||
|
||||
/* hide internal navigation fields */
|
||||
if (field.Attributes & FANavigation && !(field.Attributes & (FAConfig | FAState)))
|
||||
continue;
|
||||
|
||||
Value sval = Serialize(val);
|
||||
resultAttrs->Set(field.Name, sval);
|
||||
}
|
||||
|
||||
return resultAttrs;
|
||||
}
|
||||
|
|
@ -59,10 +59,16 @@ private:
|
|||
void UpdateSubscriptionsTimerHandler(void);
|
||||
void UpdateSubscriptions(void);
|
||||
|
||||
/* config dump */
|
||||
/* config & status dump */
|
||||
void UpdateAllConfigObjects(void);
|
||||
void SendConfigUpdate(const ConfigObject::Ptr& object, const String& typeName);
|
||||
void SendStatusUpdate(const ConfigObject::Ptr& object, const String& typeName);
|
||||
|
||||
/* utilities */
|
||||
static String FormatCheckSumBinary(const String& str);
|
||||
static String CalculateCheckSumString(const String& str);
|
||||
static String CalculateCheckSumGroups(const Array::Ptr& groups);
|
||||
static String CalculateCheckSumAttrs(const Dictionary::Ptr& attrs);
|
||||
static Dictionary::Ptr SerializeObjectAttrs(const Object::Ptr& object, int fieldType);
|
||||
|
||||
static void StateChangedHandler(const ConfigObject::Ptr& object);
|
||||
|
|
Loading…
Reference in New Issue