mirror of
https://github.com/openappsec/openappsec.git
synced 2025-09-29 19:24:26 +03:00
sync code
This commit is contained in:
@@ -276,6 +276,7 @@ void
|
||||
AgentDetails::preload()
|
||||
{
|
||||
registerExpectedConfiguration<string>("orchestration", "Agent details path");
|
||||
registerExpectedConfiguration<string>("Agent details", "File path");
|
||||
registerConfigLoadCb([this] () { readAgentDetails(); });
|
||||
}
|
||||
|
||||
|
@@ -68,6 +68,7 @@ public:
|
||||
const Maybe<string> &agent_version
|
||||
) override;
|
||||
|
||||
pair<string, string> generateTimeStamp();
|
||||
bool addAttr(const string &key, const string &val, bool allow_override = false) override;
|
||||
bool addAttr(const map<string, string> &attr, bool allow_override = false) override;
|
||||
void deleteAttr(const string &key) override;
|
||||
@@ -218,6 +219,13 @@ AgentDetailsReporter::Impl::isPersistantAttr(const std::string &key)
|
||||
return persistant_attributes.count(key) > 0;
|
||||
}
|
||||
|
||||
pair<string, string>
|
||||
AgentDetailsReporter::Impl::generateTimeStamp()
|
||||
{
|
||||
auto time_stamp = Singleton::Consume<I_TimeGet>::by<AgentDetailsReporter>()->getWalltimeStr();
|
||||
return make_pair("timestamp", time_stamp);
|
||||
}
|
||||
|
||||
bool
|
||||
AgentDetailsReporter::Impl::sendAttributes()
|
||||
{
|
||||
@@ -232,11 +240,10 @@ AgentDetailsReporter::Impl::sendAttributes()
|
||||
attributes[new_attr.first] = new_attr.second;
|
||||
}
|
||||
|
||||
|
||||
AttributesSender attr_to_send(attributes);
|
||||
if (is_server) {
|
||||
AttrSerializer<ofstream, cereal::JSONOutputArchive>(attributes, "save");
|
||||
|
||||
attr_to_send.attributes.get().insert(generateTimeStamp());
|
||||
messaging->sendAsyncMessage(HTTPMethod::PATCH, "/agents", attr_to_send);
|
||||
dbgDebug(D_AGENT_DETAILS) << "Triggered persistent message request with attributes to the Fog";
|
||||
new_attributes.clear();
|
||||
@@ -322,6 +329,36 @@ public:
|
||||
attributes = attr;
|
||||
}
|
||||
|
||||
void
|
||||
addAttr(const string &key, const string &val, bool allow_override = false)
|
||||
{
|
||||
dbgDebug(D_AGENT_DETAILS)
|
||||
<< "Trying to add new attribute. Key: "
|
||||
<< key
|
||||
<< ", Value: "
|
||||
<< val
|
||||
<< " Should allow override: "
|
||||
<< (allow_override ? "true" : "false");
|
||||
auto &attr = attributes.get();
|
||||
if (!allow_override) {
|
||||
if (attr.count(key) > 0) {
|
||||
dbgWarning(D_AGENT_DETAILS)
|
||||
<< "Cannot override an existing value with a new one. Existing Value: "
|
||||
<< (attr.count(key) > 0 ? attr[key] : "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
attr[key] = val;
|
||||
if (!attributes.isActive()) attributes.setActive(true);
|
||||
}
|
||||
|
||||
void
|
||||
addAttr(const pair<string, string> &attr, bool allow_override = false)
|
||||
{
|
||||
addAttr(attr.first, attr.second, allow_override);
|
||||
}
|
||||
|
||||
private:
|
||||
C2S_PARAM(metaDataReport, additionalMetaData);
|
||||
C2S_OPTIONAL_PARAM(string, agentVersion);
|
||||
@@ -402,6 +439,7 @@ AgentDetailsReporter::Impl::sendReport(
|
||||
additional_metadata.setAdditionalAttributes(attributes);
|
||||
}
|
||||
|
||||
additional_metadata.addAttr(generateTimeStamp());
|
||||
messaging->sendAsyncMessage(HTTPMethod::PATCH, "/agents", additional_metadata);
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "mock/mock_messaging.h"
|
||||
#include "mock/mock_mainloop.h"
|
||||
#include "mock/mock_rest_api.h"
|
||||
#include "mock/mock_time_get.h"
|
||||
#include "environment.h"
|
||||
#include "agent_details_report.h"
|
||||
|
||||
@@ -73,6 +74,7 @@ public:
|
||||
StrictMock<MockMainLoop> mock_mainloop;
|
||||
StrictMock<MockMessaging> mock_messaging;
|
||||
StrictMock<MockRestApi> mock_rest;
|
||||
StrictMock<MockTimeGet> mock_time_get;
|
||||
I_MainLoop::Routine periodic_report;
|
||||
I_AgentDetailsReporter *report;
|
||||
CPTestTempfile persistence_attr_file;
|
||||
@@ -85,6 +87,7 @@ public:
|
||||
|
||||
TEST_F(AgentReporterTest, dataReport)
|
||||
{
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
string custom_data = "Linux version 24.00.15F";
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
@@ -92,26 +95,33 @@ TEST_F(AgentReporterTest, dataReport)
|
||||
"{\n"
|
||||
" \"additionalMetaData\": {\n"
|
||||
" \"custom_data\": \"Linux version 24.00.15F\"\n"
|
||||
" }"
|
||||
"\n}",
|
||||
" },\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
_
|
||||
)).Times(1);
|
||||
AgentDataReport() << AgentReportField(custom_data);;
|
||||
AgentDataReport() << AgentReportField(custom_data);
|
||||
}
|
||||
|
||||
TEST_F(AgentReporterTest, labeledDataReport)
|
||||
{
|
||||
string data = "Linux version 24.00.15F";
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
"{\n"
|
||||
" \"additionalMetaData\": {\n"
|
||||
" \"this_is_custom_label\": \"Linux version 24.00.15F\"\n"
|
||||
" }"
|
||||
"\n}",
|
||||
" },\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
_
|
||||
@@ -123,6 +133,7 @@ TEST_F(AgentReporterTest, multiDataReport)
|
||||
{
|
||||
string custom_data = "Linux version 24.00.15F";
|
||||
string data_to_report = "Agent Version 95.95.95.00A";
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
@@ -130,8 +141,11 @@ TEST_F(AgentReporterTest, multiDataReport)
|
||||
" \"additionalMetaData\": {\n"
|
||||
" \"custom_data\": \"Linux version 24.00.15F\",\n"
|
||||
" \"this_is_custom_label\": \"Agent Version 95.95.95.00A\"\n"
|
||||
" }"
|
||||
"\n}",
|
||||
" },\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
_
|
||||
@@ -146,7 +160,7 @@ TEST_F(AgentReporterTest, multiDataReportWithRegistrationData)
|
||||
{
|
||||
string custom_data = "Linux version 24.00.15F";
|
||||
string data_to_report = "Agent Version 95.95.95.00A";
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
@@ -158,7 +172,10 @@ TEST_F(AgentReporterTest, multiDataReportWithRegistrationData)
|
||||
" \"agentVersion\": \"1.15.9\",\n"
|
||||
" \"policyVersion\": \"ccc\",\n"
|
||||
" \"platform\": \"bbb\",\n"
|
||||
" \"architecture\": \"aaa\"\n"
|
||||
" \"architecture\": \"aaa\",\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
@@ -178,11 +195,15 @@ TEST_F(AgentReporterTest, multiDataReportWithRegistrationData)
|
||||
|
||||
TEST_F(AgentReporterTest, basicAttrTest)
|
||||
{
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
"{\n"
|
||||
" \"additionalMetaData\": {}\n"
|
||||
" \"additionalMetaData\": {},\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
@@ -193,6 +214,7 @@ TEST_F(AgentReporterTest, basicAttrTest)
|
||||
AgentDataReport agent_data;
|
||||
}
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
@@ -201,7 +223,8 @@ TEST_F(AgentReporterTest, basicAttrTest)
|
||||
" \"attributes\": {\n"
|
||||
" \"1\": \"2\",\n"
|
||||
" \"a\": \"1\",\n"
|
||||
" \"c\": \"d\"\n"
|
||||
" \"c\": \"d\",\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
@@ -219,11 +242,15 @@ TEST_F(AgentReporterTest, basicAttrTest)
|
||||
AgentDataReport agent_data;
|
||||
}
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
"{\n"
|
||||
" \"additionalMetaData\": {}\n"
|
||||
" \"additionalMetaData\": {},\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
@@ -242,7 +269,7 @@ TEST_F(AgentReporterTest, advancedAttrTest)
|
||||
|
||||
EXPECT_TRUE(report->addAttr({{"c", "d"}, {"1", "2"}, {"send", "me"}}));
|
||||
EXPECT_TRUE(report->addAttr("a", "b"));
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
@@ -251,7 +278,8 @@ TEST_F(AgentReporterTest, advancedAttrTest)
|
||||
" \"1\": \"2\",\n"
|
||||
" \"a\": \"b\",\n"
|
||||
" \"c\": \"d\",\n"
|
||||
" \"send\": \"me\"\n"
|
||||
" \"send\": \"me\",\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
@@ -268,6 +296,7 @@ TEST_F(AgentReporterTest, advancedAttrTest)
|
||||
EXPECT_TRUE(report->addAttr("new", "key val"));
|
||||
EXPECT_TRUE(report->addAttr("a", "key val override", true));
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
@@ -277,7 +306,8 @@ TEST_F(AgentReporterTest, advancedAttrTest)
|
||||
" \"a\": \"key val override\",\n"
|
||||
" \"c\": \"d\",\n"
|
||||
" \"new\": \"key val\",\n"
|
||||
" \"send\": \"me\"\n"
|
||||
" \"send\": \"me\",\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}",
|
||||
MessageCategory::GENERIC,
|
||||
@@ -291,6 +321,7 @@ TEST_F(AgentReporterTest, advancedAttrTest)
|
||||
TEST_F(AgentReporterTest, RestDetailsTest)
|
||||
{
|
||||
stringstream rest_call_parameters;
|
||||
stringstream rest_call_parameters_with_timestamp;
|
||||
rest_call_parameters
|
||||
<< "{\n"
|
||||
<< " \"attributes\": {\n"
|
||||
@@ -300,17 +331,28 @@ TEST_F(AgentReporterTest, RestDetailsTest)
|
||||
<< " \"send\": \"me\"\n"
|
||||
<< " }\n"
|
||||
<< "}";
|
||||
|
||||
rest_call_parameters_with_timestamp
|
||||
<< "{\n"
|
||||
<< " \"attributes\": {\n"
|
||||
<< " \"1\": \"2\",\n"
|
||||
<< " \"a\": \"key val override\",\n"
|
||||
<< " \"c\": \"d\",\n"
|
||||
<< " \"send\": \"me\",\n"
|
||||
<< " \"timestamp\": \"Best Time ever\"\n"
|
||||
<< " }\n"
|
||||
<< "}";
|
||||
add_details_rest_cb->performRestCall(rest_call_parameters);
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
rest_call_parameters.str(),
|
||||
rest_call_parameters_with_timestamp.str(),
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
_
|
||||
)).Times(1);
|
||||
|
||||
EXPECT_TRUE(report->sendAttributes());
|
||||
|
||||
is_server_mode = false;
|
||||
@@ -365,6 +407,18 @@ TEST_F(AgentReporterTest, PersistenceAttrTest)
|
||||
"}"
|
||||
);
|
||||
|
||||
string expected_attributes_with_timestamp(
|
||||
"{\n"
|
||||
" \"attributes\": {\n"
|
||||
" \"1\": \"2\",\n"
|
||||
" \"a\": \"key val override\",\n"
|
||||
" \"c\": \"d\",\n"
|
||||
" \"send\": \"me\",\n"
|
||||
" \"timestamp\": \"Best Time ever\"\n"
|
||||
" }\n"
|
||||
"}"
|
||||
);
|
||||
|
||||
write_attributes << expected_attributes;
|
||||
write_attributes.close();
|
||||
|
||||
@@ -372,10 +426,11 @@ TEST_F(AgentReporterTest, PersistenceAttrTest)
|
||||
EXPECT_CALL(mock_rest, mockRestCall(RestAction::ADD, "agent-details-attr", _)).WillOnce(Return(true));
|
||||
agent_details_reporter_comp.init();
|
||||
|
||||
EXPECT_CALL(mock_time_get, getWalltimeStr()).WillOnce(Return("Best Time ever"));
|
||||
EXPECT_CALL(mock_messaging, sendAsyncMessage(
|
||||
HTTPMethod::PATCH,
|
||||
"/agents",
|
||||
expected_attributes,
|
||||
expected_attributes_with_timestamp,
|
||||
MessageCategory::GENERIC,
|
||||
_,
|
||||
_
|
||||
|
@@ -30,6 +30,7 @@ class AgentDetailsReporter
|
||||
Singleton::Consume<I_Messaging>,
|
||||
Singleton::Consume<I_MainLoop>,
|
||||
Singleton::Consume<I_Environment>,
|
||||
Singleton::Consume<I_TimeGet>,
|
||||
Singleton::Consume<I_RestApi>
|
||||
{
|
||||
public:
|
||||
|
@@ -53,6 +53,51 @@ private:
|
||||
std::map<std::string, std::set<std::string>> set_string_attr;
|
||||
};
|
||||
|
||||
class IpAddressRange
|
||||
{
|
||||
public:
|
||||
IpAddressRange() = default;
|
||||
IpAddressRange(const std::string &min, const std::string &max) : min(min), max(max) {}
|
||||
bool operator==(const IpAddressRange &other) const { return min == other.min && max == other.max; }
|
||||
|
||||
const std::string getMin() const { return min; }
|
||||
const std::string getMax() const { return max; }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive &ar) {
|
||||
ar(CEREAL_NVP(max), CEREAL_NVP(min));
|
||||
}
|
||||
|
||||
private:
|
||||
std::string min;
|
||||
std::string max;
|
||||
};
|
||||
|
||||
class IpAttributes
|
||||
{
|
||||
public:
|
||||
IpAttributes() = default;
|
||||
IpAttributes & addIpv4Addresses(const std::string &val);
|
||||
IpAttributes & addIpv6Addresses(const std::string &val);
|
||||
IpAttributes & addIpv4AddressRanges(const IpAddressRange &val);
|
||||
IpAttributes & addIpv6AddressRanges(const IpAddressRange &val);
|
||||
Maybe<std::vector<std::string>, void> getIpv4Addresses() const;
|
||||
Maybe<std::vector<std::string>, void> getIpv6Addresses() const;
|
||||
Maybe<std::vector<IpAddressRange>, void> getIpv4AddressRanges() const;
|
||||
Maybe<std::vector<IpAddressRange>, void> getIpv6AddressRanges() const;
|
||||
Maybe<std::string, void> genObject() const;
|
||||
bool isEmpty() const;
|
||||
bool matches(const IpAttributes &other) const;
|
||||
void serialize(cereal::JSONInputArchive &ar);
|
||||
void performOutputingSchema(std::ostream &, int);
|
||||
|
||||
private:
|
||||
std::vector<std::string> ipv4_addresses;
|
||||
std::vector<std::string> ipv6_addresses;
|
||||
std::vector<IpAddressRange> ipv4_address_ranges;
|
||||
std::vector<IpAddressRange> ipv6_address_ranges;
|
||||
};
|
||||
|
||||
class Invalidation
|
||||
{
|
||||
public:
|
||||
@@ -60,14 +105,14 @@ public:
|
||||
|
||||
Invalidation & setClassifier(ClassifierType type, const std::string &val);
|
||||
Invalidation & addMainAttr(const StrAttributes &attr);
|
||||
Invalidation & addAttr(const StrAttributes &attr);
|
||||
Invalidation & addAttr(const IpAttributes &attr);
|
||||
Invalidation & setSourceId(const std::string &id);
|
||||
Invalidation & setObjectType(ObjectType type);
|
||||
Invalidation & setInvalidationType(InvalidationType type);
|
||||
|
||||
std::string getClassifier(ClassifierType type) const { return classifiers[type]; }
|
||||
std::vector<StrAttributes> getMainAttributes() const { return main_attributes; }
|
||||
std::vector<StrAttributes> getAttributes() const { return attributes; }
|
||||
std::vector<IpAttributes> getAttributes() const { return attributes; }
|
||||
const Maybe<std::string, void> & getSourceId() const { return source_id; }
|
||||
const Maybe<ObjectType, void> & getObjectType() const { return object_type; }
|
||||
const Maybe<InvalidationType, void> & getInvalidationType() const { return invalidation_type; }
|
||||
@@ -86,10 +131,11 @@ public:
|
||||
|
||||
private:
|
||||
bool attr_matches(const std::vector<StrAttributes> ¤t, const std::vector<StrAttributes> &other) const;
|
||||
bool attr_matches(const std::vector<IpAttributes> ¤t, const std::vector<IpAttributes> &other) const;
|
||||
|
||||
EnumArray<ClassifierType, std::string, 6> classifiers;
|
||||
std::vector<StrAttributes> main_attributes;
|
||||
std::vector<StrAttributes> attributes;
|
||||
std::vector<IpAttributes> attributes;
|
||||
Maybe<std::string, void> source_id;
|
||||
Maybe<ObjectType, void> object_type;
|
||||
Maybe<InvalidationType, void> invalidation_type;
|
||||
|
@@ -254,7 +254,7 @@ private:
|
||||
C2S_OPTIONAL_PARAM(string, sourceId);
|
||||
C2S_OPTIONAL_PARAM(string, invalidationRegistrationId);
|
||||
C2S_OPTIONAL_PARAM(vector<StrAttributes>, mainAttributes);
|
||||
C2S_OPTIONAL_PARAM(vector<StrAttributes>, attributes);
|
||||
C2S_OPTIONAL_PARAM(vector<IpAttributes>, attributes);
|
||||
C2S_OPTIONAL_PARAM(string, invalidationType);
|
||||
};
|
||||
|
||||
@@ -624,7 +624,7 @@ private:
|
||||
query_request.isBulk() ? queries_uri : query_uri,
|
||||
*json_body,
|
||||
MessageCategory::INTELLIGENCE,
|
||||
global_req_md
|
||||
query_request.getReqMD().getHostName().empty() ? global_req_md : query_request.getReqMD()
|
||||
);
|
||||
if (!req_data.ok()) {
|
||||
auto response_error = req_data.getErr().toString();
|
||||
|
@@ -32,6 +32,30 @@ TEST(StringAttributesBasic, SettersAndGetters)
|
||||
EXPECT_FALSE(string_attributes.isEmpty());
|
||||
EXPECT_EQ(string_attributes.getStringAttr("attr1").unpack(), "1");
|
||||
EXPECT_EQ(string_attributes.getStringSetAttr("attr2").unpack(), vals);
|
||||
|
||||
IpAttributes attributes;
|
||||
|
||||
EXPECT_TRUE(attributes.isEmpty());
|
||||
EXPECT_FALSE(attributes.getIpv4Addresses().ok());
|
||||
EXPECT_FALSE(attributes.getIpv6Addresses().ok());
|
||||
EXPECT_FALSE(attributes.getIpv4AddressRanges().ok());
|
||||
EXPECT_FALSE(attributes.getIpv6AddressRanges().ok());
|
||||
|
||||
IpAddressRange range("1.1.1.1", "1.1.1.5");
|
||||
attributes
|
||||
.addIpv4Addresses("1.1.1.2")
|
||||
.addIpv4AddressRanges(range)
|
||||
.addIpv6Addresses("1.1.1.2")
|
||||
.addIpv6AddressRanges(range);
|
||||
|
||||
|
||||
EXPECT_FALSE(attributes.isEmpty());
|
||||
vector<string> ip_vector = {"1.1.1.2"};
|
||||
vector<IpAddressRange> ip_range_vector = {range};
|
||||
EXPECT_EQ(attributes.getIpv4Addresses().unpack(), ip_vector);
|
||||
EXPECT_EQ(attributes.getIpv4AddressRanges().unpack(), ip_range_vector);
|
||||
EXPECT_EQ(attributes.getIpv6Addresses().unpack(), ip_vector);
|
||||
EXPECT_EQ(attributes.getIpv6AddressRanges().unpack(), ip_range_vector);
|
||||
}
|
||||
|
||||
TEST(StringAttributesBasic, attr_schema)
|
||||
@@ -51,6 +75,39 @@ TEST(StringAttributesBasic, attr_schema)
|
||||
" ]\n"
|
||||
"}";
|
||||
EXPECT_EQ(ss.str(), expected_schema);
|
||||
|
||||
IpAddressRange range("1.1.1.1", "1.1.1.5");
|
||||
IpAttributes attributes = IpAttributes()
|
||||
.addIpv4Addresses("1.1.1.2")
|
||||
.addIpv4Addresses("1.1.1.3")
|
||||
.addIpv4AddressRanges(range)
|
||||
.addIpv6Addresses("1.1.1.4")
|
||||
.addIpv6AddressRanges(range);
|
||||
stringstream attr_ss;
|
||||
attributes.performOutputingSchema(attr_ss, 0);
|
||||
expected_schema =
|
||||
"{\n"
|
||||
" \"ipv4Addresses\": [\n"
|
||||
" \"1.1.1.2\",\n"
|
||||
" \"1.1.1.3\"\n"
|
||||
" ],\n"
|
||||
" \"ipv6Addresses\": [\n"
|
||||
" \"1.1.1.4\"\n"
|
||||
" ],\n"
|
||||
" \"ipv4AddressesRange\": [\n"
|
||||
" {\n"
|
||||
" \"max\": \"1.1.1.5\",\n"
|
||||
" \"min\": \"1.1.1.1\"\n"
|
||||
" }\n"
|
||||
" ],\n"
|
||||
" \"ipv6AddressesRange\": [\n"
|
||||
" {\n"
|
||||
" \"max\": \"1.1.1.5\",\n"
|
||||
" \"min\": \"1.1.1.1\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
"}";
|
||||
EXPECT_EQ(attr_ss.str(), expected_schema);
|
||||
}
|
||||
|
||||
TEST(StringAttributesBasic, Matching)
|
||||
@@ -105,6 +162,20 @@ TEST(StringAttributesBasic, genObject)
|
||||
|
||||
string expected_json = "{ \"attr1\": \"1\", \"attr2\": [ \"2\", \"3\" ] }";
|
||||
EXPECT_EQ(string_attributes.genObject().unpack(), expected_json);
|
||||
|
||||
IpAddressRange range("1.1.1.1", "1.1.1.5");
|
||||
IpAttributes attributes = IpAttributes()
|
||||
.addIpv4Addresses("1.1.1.2")
|
||||
.addIpv4Addresses("1.1.1.3")
|
||||
.addIpv4AddressRanges(range)
|
||||
.addIpv6Addresses("1.1.1.4")
|
||||
.addIpv6AddressRanges(range);
|
||||
|
||||
expected_json =
|
||||
"{ \"ipv4Addresses\": [ \"1.1.1.2\", \"1.1.1.3\" ], \"ipv6Addresses\": [ \"1.1.1.4\" ], "
|
||||
"\"ipv4AddressesRange\": [ { \"max\": \"1.1.1.5\", \"min\": \"1.1.1.1\" } ], "
|
||||
"\"ipv6AddressesRange\": [ { \"max\": \"1.1.1.5\", \"min\": \"1.1.1.1\" } ] }";
|
||||
EXPECT_EQ(attributes.genObject().unpack(), expected_json);
|
||||
}
|
||||
|
||||
TEST(InvalidationBasic, SettersAndGetters)
|
||||
@@ -125,15 +196,15 @@ TEST(InvalidationBasic, SettersAndGetters)
|
||||
EXPECT_FALSE(invalidation.getInvalidationType().ok());
|
||||
|
||||
set<string> main_vals = { "2", "3" };
|
||||
set<string> vals = { "5", "6" };
|
||||
vector<string> vals = {"1.1.1.1", "2.2.2.2"};
|
||||
|
||||
auto main_attr = StrAttributes()
|
||||
.addStringAttr("main_attr1", "1")
|
||||
.addStringSetAttr("main_attr2", main_vals);
|
||||
|
||||
auto attr = StrAttributes()
|
||||
.addStringAttr("attr1", "4")
|
||||
.addStringSetAttr("attr2", vals);
|
||||
auto attr = IpAttributes()
|
||||
.addIpv4Addresses("1.1.1.1")
|
||||
.addIpv4Addresses("2.2.2.2");
|
||||
|
||||
invalidation
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
@@ -148,8 +219,7 @@ TEST(InvalidationBasic, SettersAndGetters)
|
||||
EXPECT_EQ(invalidation.getClassifier(ClassifierType::FAMILY), "ccc");
|
||||
EXPECT_EQ(invalidation.getMainAttributes().begin()->getStringAttr("main_attr1").unpack(), "1");
|
||||
EXPECT_EQ(invalidation.getMainAttributes().begin()->getStringSetAttr("main_attr2").unpack(), main_vals);
|
||||
EXPECT_EQ(invalidation.getAttributes().begin()->getStringAttr("attr1").unpack(), "4");
|
||||
EXPECT_EQ(invalidation.getAttributes().begin()->getStringSetAttr("attr2").unpack(), vals);
|
||||
EXPECT_EQ(invalidation.getAttributes().begin()->getIpv4Addresses().unpack(), vals);
|
||||
EXPECT_EQ(invalidation.getSourceId().unpack(), "id");
|
||||
EXPECT_EQ(invalidation.getObjectType().unpack(), Intelligence::ObjectType::ASSET);
|
||||
EXPECT_EQ(invalidation.getInvalidationType().unpack(), InvalidationType::DELETE);
|
||||
@@ -164,9 +234,9 @@ TEST(InvalidationBasic, Matching)
|
||||
.addStringAttr("main_attr1", "1")
|
||||
.addStringSetAttr("main_attr2", main_vals);
|
||||
|
||||
auto attr = StrAttributes()
|
||||
.addStringAttr("attr1", "4")
|
||||
.addStringSetAttr("attr2", vals);
|
||||
auto attr = IpAttributes()
|
||||
.addIpv4Addresses("1.1.1.1")
|
||||
.addIpv4Addresses("2.2.2.2");
|
||||
|
||||
auto base_invalidation = Invalidation("aaa")
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
@@ -179,10 +249,9 @@ TEST(InvalidationBasic, Matching)
|
||||
.addStringSetAttr("main_attr2", main_vals)
|
||||
.addStringAttr("main_attr3", "6");
|
||||
|
||||
auto matching_attr = StrAttributes()
|
||||
.addStringAttr("attr1", "4")
|
||||
.addStringSetAttr("attr2", vals)
|
||||
.addStringAttr("attr3", "7");
|
||||
auto matching_attr = IpAttributes()
|
||||
.addIpv4Addresses("1.1.1.1")
|
||||
.addIpv4Addresses("2.2.2.2");
|
||||
|
||||
auto matching_invalidation = Invalidation("aaa")
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
@@ -212,10 +281,9 @@ TEST(InvalidationBasic, Matching)
|
||||
|
||||
EXPECT_FALSE(base_invalidation.matches(missing_attr_invalidation_main));
|
||||
|
||||
auto missing_attr = StrAttributes()
|
||||
.addStringAttr("attr1", "4")
|
||||
.addStringAttr("attr2", "2")
|
||||
.addStringAttr("attr3", "7");
|
||||
auto missing_attr = IpAttributes()
|
||||
.addIpv4Addresses("2.2.2.2")
|
||||
.addIpv4Addresses("3.3.3.3");
|
||||
|
||||
auto missing_attr_invalidation = Invalidation("aaa")
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
@@ -280,7 +348,7 @@ public:
|
||||
intelligence.preload();
|
||||
intelligence.init();
|
||||
main_attr.addStringAttr("attr2", "2");
|
||||
attr.addStringAttr("attr3", "3");
|
||||
attr.addIpv4Addresses("1.1.1.1");
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -291,7 +359,7 @@ public:
|
||||
}
|
||||
|
||||
StrAttributes main_attr;
|
||||
StrAttributes attr;
|
||||
IpAttributes attr;
|
||||
StrictMock<MockMessaging> messaging_mock;
|
||||
StrictMock<MockMainLoop> mock_ml;
|
||||
NiceMock<MockTimeGet> mock_time;
|
||||
@@ -350,7 +418,7 @@ TEST_F(IntelligenceInvalidation, sending_public_invalidation)
|
||||
"\"objectType\": \"asset\", "
|
||||
"\"sourceId\": \"id\", "
|
||||
"\"mainAttributes\": [ { \"attr2\": \"2\" } ], "
|
||||
"\"attributes\": [ { \"attr3\": \"3\" } ]"
|
||||
"\"attributes\": [ { \"ipv4Addresses\": [ \"1.1.1.1\" ] } ]"
|
||||
" } ] }";
|
||||
EXPECT_EQ(invalidation_json, expected_json);
|
||||
EXPECT_FALSE(md.getConnectionFlags().isSet(MessageConnectionConfig::UNSECURE_CONN));
|
||||
@@ -390,7 +458,7 @@ TEST_F(IntelligenceInvalidation, multiple_assets_invalidation)
|
||||
"\"objectType\": \"asset\", "
|
||||
"\"sourceId\": \"id\", "
|
||||
"\"mainAttributes\": [ { \"attr2\": \"2\" }, { \"attr2\": \"22\", \"attr3\": [ \"33\", \"44\" ] } ], "
|
||||
"\"attributes\": [ { \"attr3\": \"3\" } ]"
|
||||
"\"attributes\": [ { \"ipv4Addresses\": [ \"1.1.1.1\" ] } ]"
|
||||
" } ] }";
|
||||
EXPECT_EQ(invalidation_json, expected_json);
|
||||
}
|
||||
@@ -439,7 +507,7 @@ TEST_F(IntelligenceInvalidation, sending_private_invalidation)
|
||||
"\"objectType\": \"asset\", "
|
||||
"\"sourceId\": \"id\", "
|
||||
"\"mainAttributes\": [ { \"attr2\": \"2\" } ], "
|
||||
"\"attributes\": [ { \"attr3\": \"3\" } ]"
|
||||
"\"attributes\": [ { \"ipv4Addresses\": [ \"1.1.1.1\" ] } ]"
|
||||
" } ] }";
|
||||
EXPECT_EQ(invalidation_json, expected_json);
|
||||
EXPECT_TRUE(md.getConnectionFlags().isSet(MessageConnectionConfig::UNSECURE_CONN));
|
||||
@@ -484,7 +552,7 @@ TEST_F(IntelligenceInvalidation, register_for_invalidation)
|
||||
EXPECT_THAT(body, HasSubstr("\"url\": \"http://127.0.0.1:7000/set-new-invalidation\""));
|
||||
EXPECT_THAT(body, HasSubstr("\"apiVersion\": \"v2\", \"communicationType\": \"sync\""));
|
||||
EXPECT_THAT(body, HasSubstr("\"mainAttributes\": [ { \"attr2\": \"2\" } ]"));
|
||||
EXPECT_THAT(body, HasSubstr("\"attributes\": [ { \"attr3\": \"3\" } ]"));
|
||||
EXPECT_THAT(body, HasSubstr("\"attributes\": [ { \"ipv4Addresses\": [ \"1.1.1.1\" ] } ]"));
|
||||
EXPECT_TRUE(md.getConnectionFlags().isSet(MessageConnectionConfig::UNSECURE_CONN));
|
||||
EXPECT_THAT(body, HasSubstr("\"capabilities\": { \"getBulkCallback\": true }"));
|
||||
|
||||
@@ -888,11 +956,19 @@ TEST_F(IntelligenceInvalidation, invalidation_cb_match_by_registration_id)
|
||||
configuration << "}";
|
||||
Singleton::Consume<Config::I_Config>::from(conf)->loadConfiguration(configuration);
|
||||
|
||||
IpAddressRange range("1.1.1.1", "1.1.1.5");
|
||||
IpAttributes attributes = IpAttributes()
|
||||
.addIpv4Addresses("1.1.1.2")
|
||||
.addIpv4AddressRanges(range)
|
||||
.addIpv6Addresses("1.1.1.2")
|
||||
.addIpv6AddressRanges(range);
|
||||
|
||||
auto base_main_attr2 = StrAttributes()
|
||||
.addStringAttr("attr3", "3");
|
||||
auto invalidation_to_register = Invalidation("aaa")
|
||||
.addMainAttr(main_attr)
|
||||
.addMainAttr(base_main_attr2)
|
||||
.addAttr(attributes)
|
||||
.setSourceId("id")
|
||||
.setClassifier(ClassifierType::FAMILY, "ccc")
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
@@ -911,6 +987,7 @@ TEST_F(IntelligenceInvalidation, invalidation_cb_match_by_registration_id)
|
||||
|
||||
auto matching_invalidation = Invalidation("aaa")
|
||||
.addMainAttr(matching_second_main_attribute)
|
||||
.addAttr(attributes)
|
||||
.setSourceId("id")
|
||||
.setClassifier(ClassifierType::FAMILY, "ccc")
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
@@ -919,6 +996,7 @@ TEST_F(IntelligenceInvalidation, invalidation_cb_match_by_registration_id)
|
||||
|
||||
auto invalidation_2_to_register = Invalidation("aaa")
|
||||
.addMainAttr(base_main_attr2)
|
||||
.addAttr(attributes)
|
||||
.setSourceId("id")
|
||||
.setClassifier(ClassifierType::FAMILY, "ccc")
|
||||
.setClassifier(ClassifierType::CATEGORY, "bbb")
|
||||
|
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "i_intelligence_is_v2.h"
|
||||
|
||||
USE_DEBUG_FLAG(D_INTELLIGENCE);
|
||||
|
||||
using namespace Intelligence;
|
||||
using namespace std;
|
||||
|
||||
@@ -203,6 +205,18 @@ Invalidation::attr_matches(const vector<StrAttributes> ¤t, const vector<St
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Invalidation::attr_matches(const vector<IpAttributes> ¤t, const vector<IpAttributes> &other) const
|
||||
{
|
||||
if (current.empty()) return true;
|
||||
for (const auto &attr : current) {
|
||||
for(const auto &other_attr : other) {
|
||||
if (attr.matches(other_attr)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Invalidation::matches(const Invalidation &other) const
|
||||
{
|
||||
@@ -230,7 +244,7 @@ Invalidation::matches(const Invalidation &other) const
|
||||
}
|
||||
|
||||
Invalidation &
|
||||
Invalidation::addAttr(const StrAttributes &attr)
|
||||
Invalidation::addAttr(const IpAttributes &attr)
|
||||
{
|
||||
attributes.emplace_back(attr);
|
||||
return *this;
|
||||
@@ -378,3 +392,224 @@ StrAttributes::performOutputingSchema(ostream &out, int level) {
|
||||
}
|
||||
RestHelper::printIndent(out, level) << "}";
|
||||
}
|
||||
|
||||
IpAttributes &
|
||||
IpAttributes::addIpv4Addresses(const string &val)
|
||||
{
|
||||
ipv4_addresses.push_back(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IpAttributes &
|
||||
IpAttributes::addIpv6Addresses(const string &val)
|
||||
{
|
||||
ipv6_addresses.push_back(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IpAttributes &
|
||||
IpAttributes::addIpv4AddressRanges(const IpAddressRange &val)
|
||||
{
|
||||
ipv4_address_ranges.push_back(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
IpAttributes &
|
||||
IpAttributes::addIpv6AddressRanges(const IpAddressRange &val)
|
||||
{
|
||||
ipv6_address_ranges.push_back(val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Maybe<vector<string>, void>
|
||||
IpAttributes::getIpv4Addresses() const
|
||||
{
|
||||
if (ipv4_addresses.empty()) return genError<void>();
|
||||
return ipv4_addresses;
|
||||
}
|
||||
|
||||
Maybe<vector<string>, void>
|
||||
IpAttributes::getIpv6Addresses() const
|
||||
{
|
||||
if (ipv6_addresses.empty()) return genError<void>();
|
||||
return ipv6_addresses;
|
||||
}
|
||||
|
||||
Maybe<vector<IpAddressRange>, void>
|
||||
IpAttributes::getIpv4AddressRanges() const
|
||||
{
|
||||
if (ipv4_address_ranges.empty()) return genError<void>();
|
||||
return ipv4_address_ranges;
|
||||
}
|
||||
|
||||
Maybe<vector<IpAddressRange>, void>
|
||||
IpAttributes::getIpv6AddressRanges() const
|
||||
{
|
||||
if (ipv6_address_ranges.empty()) return genError<void>();
|
||||
return ipv6_address_ranges;
|
||||
}
|
||||
|
||||
Maybe<string, void>
|
||||
IpAttributes::genObject() const
|
||||
{
|
||||
stringstream attributes_ss;
|
||||
if (this->isEmpty()) return genError<void>();
|
||||
bool internal_first = true;
|
||||
bool first = true;
|
||||
attributes_ss << "{ ";
|
||||
if (!ipv4_addresses.empty()) {
|
||||
attributes_ss << "\"ipv4Addresses\": [ ";
|
||||
for (auto &attr : ipv4_addresses) {
|
||||
if (!internal_first) attributes_ss << ", ";
|
||||
attributes_ss << "\"" << attr << "\"";
|
||||
internal_first = false;
|
||||
}
|
||||
attributes_ss << " ]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!ipv6_addresses.empty()) {
|
||||
if (!first) attributes_ss << ", ";
|
||||
attributes_ss << "\"ipv6Addresses\": [ ";
|
||||
internal_first = true;
|
||||
for (auto &attr : ipv6_addresses) {
|
||||
if (!internal_first) attributes_ss << ", ";
|
||||
attributes_ss << "\"" << attr << "\"";
|
||||
internal_first = false;
|
||||
}
|
||||
attributes_ss << " ]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!ipv4_address_ranges.empty()) {
|
||||
if (!first) attributes_ss << ", ";
|
||||
attributes_ss << "\"ipv4AddressesRange\": [ ";
|
||||
internal_first = true;
|
||||
for (auto &attr : ipv4_address_ranges) {
|
||||
if (!internal_first) attributes_ss << ", ";
|
||||
attributes_ss << "{ \"max\": \"" << attr.getMax() << "\", \"min\": \"" << attr.getMin() << "\" }";
|
||||
internal_first = false;
|
||||
}
|
||||
attributes_ss << " ]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!ipv6_address_ranges.empty()) {
|
||||
if (!first) attributes_ss << ", ";
|
||||
attributes_ss << "\"ipv6AddressesRange\": [ ";
|
||||
internal_first = true;
|
||||
for (auto &attr : ipv6_address_ranges) {
|
||||
if (!internal_first) attributes_ss << ", ";
|
||||
attributes_ss << "{ \"max\": \"" << attr.getMax() << "\", \"min\": \"" << attr.getMin() << "\" }";
|
||||
internal_first = false;
|
||||
}
|
||||
attributes_ss << " ]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
attributes_ss << " }";
|
||||
return attributes_ss.str();
|
||||
}
|
||||
|
||||
bool
|
||||
IpAttributes::isEmpty() const
|
||||
{
|
||||
return
|
||||
ipv4_addresses.empty() &&
|
||||
ipv6_addresses.empty() &&
|
||||
ipv4_address_ranges.empty() &&
|
||||
ipv6_address_ranges.empty();
|
||||
}
|
||||
|
||||
bool
|
||||
IpAttributes::matches(const IpAttributes &other) const
|
||||
{
|
||||
return
|
||||
ipv4_addresses == other.ipv4_addresses &&
|
||||
ipv6_addresses == other.ipv6_addresses &&
|
||||
ipv4_address_ranges == other.ipv4_address_ranges &&
|
||||
ipv6_address_ranges == other.ipv6_address_ranges;
|
||||
}
|
||||
|
||||
void
|
||||
IpAttributes::serialize(cereal::JSONInputArchive &ar)
|
||||
{
|
||||
try {
|
||||
ar(cereal::make_nvp("ipv4Addresses", ipv4_addresses));
|
||||
ar(cereal::make_nvp("ipv4AddressesRange", ipv4_address_ranges));
|
||||
ar(cereal::make_nvp("ipv6Addresses", ipv6_addresses));
|
||||
ar(cereal::make_nvp("ipv6AddressesRange", ipv6_address_ranges));
|
||||
} catch (cereal::Exception &e) {
|
||||
dbgError(D_INTELLIGENCE) << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IpAttributes::performOutputingSchema(ostream &out, int level)
|
||||
{
|
||||
bool first = true;
|
||||
bool internal_first = true;
|
||||
RestHelper::printIndent(out, level) << "{\n";
|
||||
|
||||
if (!ipv4_addresses.empty()) {
|
||||
RestHelper::printIndent(out, level + 1) << "\"ipv4Addresses\": [\n";
|
||||
for (auto &attr : ipv4_addresses) {
|
||||
if (!internal_first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 2) << "\"" << attr << "\"";
|
||||
internal_first = false;
|
||||
}
|
||||
out << "\n";
|
||||
RestHelper::printIndent(out, level + 1) << "]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!ipv6_addresses.empty()) {
|
||||
if (!first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 1) << "\"ipv6Addresses\": [\n";
|
||||
internal_first = true;
|
||||
for (auto &attr : ipv6_addresses) {
|
||||
if (!internal_first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 2) << "\"" << attr << "\"";
|
||||
internal_first = false;
|
||||
}
|
||||
out << "\n";
|
||||
RestHelper::printIndent(out, level + 1) << "]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!ipv4_address_ranges.empty()) {
|
||||
if (!first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 1) << "\"ipv4AddressesRange\": [\n";
|
||||
internal_first = true;
|
||||
for (auto &attr : ipv4_address_ranges) {
|
||||
if (!internal_first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 2) << "{\n";
|
||||
RestHelper::printIndent(out, level + 3) << "\"max\": \"" << attr.getMax() << "\",\n";
|
||||
RestHelper::printIndent(out, level + 3) << "\"min\": \"" << attr.getMin() << "\"\n";
|
||||
RestHelper::printIndent(out, level + 2) << "}";
|
||||
internal_first = false;
|
||||
}
|
||||
out << "\n";
|
||||
RestHelper::printIndent(out, level + 1) << "]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!ipv6_address_ranges.empty()) {
|
||||
if (!first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 1) << "\"ipv6AddressesRange\": [\n";
|
||||
internal_first = true;
|
||||
for (auto &attr : ipv6_address_ranges) {
|
||||
if (!internal_first) out << ",\n";
|
||||
RestHelper::printIndent(out, level + 2) << "{\n";
|
||||
RestHelper::printIndent(out, level + 3) << "\"max\": \"" << attr.getMax() << "\",\n";
|
||||
RestHelper::printIndent(out, level + 3) << "\"min\": \"" << attr.getMin() << "\"\n";
|
||||
RestHelper::printIndent(out, level + 2) << "}";
|
||||
internal_first = false;
|
||||
}
|
||||
out << "\n";
|
||||
RestHelper::printIndent(out, level + 1) << "]";
|
||||
first = false;
|
||||
}
|
||||
|
||||
RestHelper::printIndent(out, level) << "\n}";
|
||||
}
|
||||
|
@@ -163,10 +163,14 @@ RestServer::Impl::init()
|
||||
}
|
||||
}
|
||||
|
||||
bool is_ipv6 = false;
|
||||
if (accept_get_from_external_ip) {
|
||||
is_ipv6 = true;
|
||||
fd = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
} else {
|
||||
}
|
||||
if (fd == -1) {
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
is_ipv6 = false;
|
||||
}
|
||||
dbgAssert(fd >= 0) << alert << "Failed to open a socket";
|
||||
|
||||
@@ -175,7 +179,8 @@ RestServer::Impl::init()
|
||||
dbgWarning(D_API) << "Could not set the socket options";
|
||||
}
|
||||
|
||||
if (accept_get_from_external_ip) {
|
||||
if (is_ipv6) {
|
||||
dbgDebug(D_API) << "IPv6 socket opened successfully";
|
||||
int option = 0;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &option, sizeof(option)) < 0) {
|
||||
dbgWarning(D_API) << "Could not set the IPV6_V6ONLY option";
|
||||
@@ -185,16 +190,24 @@ RestServer::Impl::init()
|
||||
bzero(&addr6, sizeof(addr6));
|
||||
addr6.sin6_family = AF_INET6;
|
||||
addr6.sin6_addr = in6addr_any;
|
||||
dbgDebug(D_API) << "Socket listening on any address";
|
||||
|
||||
while (!bindRestServerSocket(addr6, port_range)) {
|
||||
mainloop->yield(bind_retry_interval_msec);
|
||||
}
|
||||
listening_port = ntohs(addr6.sin6_port);
|
||||
} else {
|
||||
dbgDebug(D_API) << "IPv4 socket opened successfully";
|
||||
struct sockaddr_in addr;
|
||||
bzero(&addr, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
if (accept_get_from_external_ip) {
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
dbgDebug(D_API) << "Socket listening on any address";
|
||||
} else {
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
dbgDebug(D_API) << "Socket listening on local address";
|
||||
}
|
||||
|
||||
while (!bindRestServerSocket(addr, port_range)) {
|
||||
mainloop->yield(bind_retry_interval_msec);
|
||||
|
Reference in New Issue
Block a user