mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-04 00:00:14 -04:00
sw-collector: Query central collector database
This commit is contained in:
parent
8ba6bf511e
commit
74aa1626d2
@ -13,5 +13,17 @@ sw-collector.history =
|
||||
sw-collector.first_time = 0000-00-00T00:00:00Z
|
||||
Time in UTC when the Linux OS was installed.
|
||||
|
||||
sw-collector.rest_api.uri =
|
||||
HTTP URI of the central collector's REST API.
|
||||
|
||||
sw-collector.rest_api.timeout = 120
|
||||
Timeout of REST API HTTP POST transaction.
|
||||
|
||||
sw-collector.tag_creator.name = strongSwan Project
|
||||
Name of the tagCreator entity.
|
||||
|
||||
sw-collector.tag_creator.regid = strongswan.org
|
||||
regid of the tagCreator entity.
|
||||
|
||||
sw-collector.load =
|
||||
Plugins to load in sw-collector tool.
|
||||
|
@ -23,7 +23,7 @@ AM_CPPFLAGS = \
|
||||
-DPLUGINS=\""random openssl sqlite curl"\"
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS)
|
||||
$(PLUGIN_CFLAGS) $(json_CFLAGS)
|
||||
|
||||
imcv_LTLIBRARIES = imc-swima.la
|
||||
|
||||
@ -37,11 +37,14 @@ ipsec_PROGRAMS = sw-collector
|
||||
sw_collector_SOURCES = \
|
||||
sw_collector/sw-collector.c \
|
||||
sw_collector/sw_collector_db.h sw_collector/sw_collector_db.c \
|
||||
sw_collector/sw_collector_history.h sw_collector/sw_collector_history.c
|
||||
sw_collector/sw_collector_history.h sw_collector/sw_collector_history.c \
|
||||
sw_collector/sw_collector_rest_api.h sw_collector/sw_collector_rest_api.c
|
||||
|
||||
sw_collector_LDADD = \
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la \
|
||||
$(top_builddir)/src/libimcv/libimcv.la
|
||||
$(top_builddir)/src/libstrongswan/libstrongswan.la \
|
||||
$(top_builddir)/src/libimcv/libimcv.la \
|
||||
$(json_LIBS)
|
||||
|
||||
sw-collector.o : $(top_builddir)/config.status
|
||||
|
||||
templatesdir = $(pkgdatadir)/templates/database/sw-collector
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "sw_collector_db.h"
|
||||
#include "sw_collector_history.h"
|
||||
#include "sw_collector_rest_api.h"
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/debug.h>
|
||||
@ -41,7 +42,9 @@ typedef enum collector_op_t collector_op_t;
|
||||
|
||||
enum collector_op_t {
|
||||
COLLECTOR_OP_EXTRACT,
|
||||
COLLECTOR_OP_LIST
|
||||
COLLECTOR_OP_LIST,
|
||||
COLLECTOR_OP_UNREGISTERED,
|
||||
COLLECTOR_OP_GENERATE
|
||||
};
|
||||
|
||||
/**
|
||||
@ -108,6 +111,7 @@ static void usage(void)
|
||||
Usage:\n\
|
||||
sw-collector --help\n\
|
||||
sw-collector [--debug <level>] [--quiet] --list\n\
|
||||
sw-collector [--debug <level>] [--quiet] --unregistered|--generate\n\
|
||||
sw-collector [--debug <level>] [--quiet] [--count <event count>]\n");
|
||||
}
|
||||
|
||||
@ -129,12 +133,14 @@ static collector_op_t do_args(int argc, char *argv[])
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "count", required_argument, NULL, 'c' },
|
||||
{ "debug", required_argument, NULL, 'd' },
|
||||
{ "generate", no_argument, NULL, 'g' },
|
||||
{ "list", no_argument, NULL, 'l' },
|
||||
{ "quiet", no_argument, NULL, 'q' },
|
||||
{ "unregistered", no_argument, NULL, 'u' },
|
||||
{ 0,0,0,0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "hc:d:lq", long_opts, NULL);
|
||||
c = getopt_long(argc, argv, "hc:d:lqu", long_opts, NULL);
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
@ -149,12 +155,18 @@ static collector_op_t do_args(int argc, char *argv[])
|
||||
case 'd':
|
||||
debug_level = atoi(optarg);
|
||||
continue;
|
||||
case 'g':
|
||||
op = COLLECTOR_OP_GENERATE;
|
||||
continue;
|
||||
case 'l':
|
||||
op = COLLECTOR_OP_LIST;
|
||||
continue;
|
||||
case 'q':
|
||||
stderr_quiet = TRUE;
|
||||
continue;
|
||||
case 'u':
|
||||
op = COLLECTOR_OP_UNREGISTERED;
|
||||
continue;
|
||||
default:
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
@ -177,8 +189,8 @@ static int extract_history(sw_collector_db_t *db)
|
||||
bool skip = TRUE;
|
||||
|
||||
/* open history file for reading */
|
||||
history_path= lib->settings->get_str(lib->settings, "sw-collector.history",
|
||||
NULL);
|
||||
history_path= lib->settings->get_str(lib->settings, "%s.history", NULL,
|
||||
lib->ns);
|
||||
if (!history_path)
|
||||
{
|
||||
fprintf(stderr, "sw-collector.history path not set.\n");
|
||||
@ -308,7 +320,7 @@ end:
|
||||
}
|
||||
|
||||
/**
|
||||
* List all software identifiers stored in the collector database
|
||||
* List all endpoint software identifiers stored in local collector database
|
||||
*/
|
||||
static int list_identifiers(sw_collector_db_t *db)
|
||||
{
|
||||
@ -316,7 +328,7 @@ static int list_identifiers(sw_collector_db_t *db)
|
||||
char *name, *package, *version;
|
||||
uint32_t count = 0, installed_count = 0, installed;
|
||||
|
||||
e = db->create_sw_enumerator(db, FALSE);
|
||||
e = db->create_sw_enumerator(db, SW_QUERY_ALL);
|
||||
if (!e)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
@ -337,6 +349,156 @@ static int list_identifiers(sw_collector_db_t *db)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static bool query_registry(sw_collector_rest_api_t *rest_api, bool installed)
|
||||
{
|
||||
sw_collector_db_query_t type;
|
||||
enumerator_t *enumerator;
|
||||
char *sw_id;
|
||||
int count = 0;
|
||||
|
||||
type = installed ? SW_QUERY_INSTALLED : SW_QUERY_DELETED;
|
||||
enumerator = rest_api->create_sw_enumerator(rest_api, type);
|
||||
if (!enumerator)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
while (enumerator->enumerate(enumerator, &sw_id))
|
||||
{
|
||||
printf("%s,%s\n", sw_id, installed ? "1" : "0");
|
||||
count++;
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
DBG1(DBG_IMC, "%d %s software identifiers not registered", count,
|
||||
installed ? "installed" : "deleted");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List all endpoint software identifiers stored in local collector database
|
||||
* that are not registered yet in central collelector database
|
||||
*/
|
||||
static int unregistered_identifiers(sw_collector_db_t *db)
|
||||
{
|
||||
sw_collector_rest_api_t *rest_api;
|
||||
int status = EXIT_SUCCESS;
|
||||
|
||||
rest_api = sw_collector_rest_api_create(db);
|
||||
if (!rest_api)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* List installed software identifiers not registered centrally */
|
||||
if (!query_registry(rest_api, TRUE))
|
||||
{
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* List deleted software identifiers not registered centrally */
|
||||
if (!query_registry(rest_api, FALSE))
|
||||
{
|
||||
status = EXIT_FAILURE;
|
||||
}
|
||||
rest_api->destroy(rest_api);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a minimalistic ISO 19770-2:2015 SWID tag
|
||||
*/
|
||||
static char* generate_tag(char *name, char *package, char *version,
|
||||
char* entity, char *regid, char *product)
|
||||
{
|
||||
char *tag_id, *tag;
|
||||
int res;
|
||||
|
||||
tag_id = strstr(name, "__");
|
||||
if (!tag_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
tag_id += 2;
|
||||
|
||||
res = asprintf(&tag, "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
|
||||
"<SoftwareIdentity name=\"%s\" tagId=\"%s\" version=\"%s\" "
|
||||
"versionScheme=\"alphanumeric\" "
|
||||
"xmlns=\"http://standards.iso.org/iso/19770/-2/2015/schema.xsd\">"
|
||||
"<Entity name=\"%s\" regid=\"%s\" role=\"tagCreator\"/>"
|
||||
"<Meta product=\"%s\"/>"
|
||||
"</SoftwareIdentity>",
|
||||
package, tag_id, version, entity, regid, product);
|
||||
|
||||
return (res == -1) ? NULL : tag;
|
||||
}
|
||||
|
||||
static int generate_tags(sw_collector_db_t *db)
|
||||
{
|
||||
sw_collector_history_t *os_info;
|
||||
sw_collector_rest_api_t *rest_api;
|
||||
char *pos, *name, *package, *version, *entity, *regid, *product, *tag;
|
||||
enumerator_t *enumerator;
|
||||
uint32_t sw_id;
|
||||
int status = EXIT_FAILURE;
|
||||
|
||||
entity = lib->settings->get_str(lib->settings, "%s.tag_creator.name",
|
||||
"strongSwan Project", lib->ns);
|
||||
regid = lib->settings->get_str(lib->settings, "%s.tag_creator.regid",
|
||||
"strongswan.org", lib->ns);
|
||||
|
||||
os_info = sw_collector_history_create(db, 0);
|
||||
if (!os_info)
|
||||
{
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
os_info->get_os(os_info, &product);
|
||||
|
||||
rest_api = sw_collector_rest_api_create(db);
|
||||
if (!rest_api)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
|
||||
enumerator = rest_api->create_sw_enumerator(rest_api, SW_QUERY_DELETED);
|
||||
if (!enumerator)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
while (enumerator->enumerate(enumerator, &name))
|
||||
{
|
||||
sw_id = db->get_sw_id(db, name, &package, &version, NULL, NULL);
|
||||
if (sw_id)
|
||||
{
|
||||
/* Remove architecture from package name */
|
||||
pos = strchr(package, ':');
|
||||
if (pos)
|
||||
{
|
||||
*pos = '\0';
|
||||
}
|
||||
tag = generate_tag(name, package, version, entity, regid, product);
|
||||
if (tag)
|
||||
{
|
||||
printf("%s\n", tag);
|
||||
free(tag);
|
||||
count++;
|
||||
}
|
||||
free(package);
|
||||
free(version);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
status = EXIT_SUCCESS;
|
||||
DBG1(DBG_IMC, "%d tags for deleted unregistered software identifiers",
|
||||
count);
|
||||
|
||||
end:
|
||||
os_info->destroy(os_info);
|
||||
DESTROY_IF(rest_api);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
sw_collector_db_t *db = NULL;
|
||||
@ -362,13 +524,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* load sw-collector plugins */
|
||||
if (!lib->plugins->load(lib->plugins,
|
||||
lib->settings->get_str(lib->settings, "sw-collector.load", PLUGINS)))
|
||||
lib->settings->get_str(lib->settings, "%s.load", PLUGINS, lib->ns)))
|
||||
{
|
||||
exit(SS_RC_INITIALIZATION_FAILED);
|
||||
}
|
||||
|
||||
/* connect to sw-collector database */
|
||||
uri = lib->settings->get_str(lib->settings, "sw-collector.database", NULL);
|
||||
uri = lib->settings->get_str(lib->settings, "%s.database", NULL, lib->ns);
|
||||
if (!uri)
|
||||
{
|
||||
fprintf(stderr, "sw-collector.database URI not set.\n");
|
||||
@ -389,6 +551,11 @@ int main(int argc, char *argv[])
|
||||
case COLLECTOR_OP_LIST:
|
||||
status = list_identifiers(db);
|
||||
break;
|
||||
case COLLECTOR_OP_UNREGISTERED:
|
||||
status = unregistered_identifiers(db);
|
||||
break;
|
||||
case COLLECTOR_OP_GENERATE:
|
||||
status = generate_tags(db);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -108,8 +108,8 @@ METHOD(sw_collector_db_t, add_sw_event, bool,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(sw_collector_db_t, get_sw_id, uint32_t,
|
||||
private_sw_collector_db_t *this, char *package, char *version, char *name,
|
||||
METHOD(sw_collector_db_t, set_sw_id, uint32_t,
|
||||
private_sw_collector_db_t *this, char *name, char *package, char *version,
|
||||
uint8_t source, bool installed, bool check)
|
||||
{
|
||||
uint32_t sw_id = 0, status;
|
||||
@ -179,23 +179,67 @@ METHOD(sw_collector_db_t, get_sw_id, uint32_t,
|
||||
return sw_id;
|
||||
}
|
||||
|
||||
METHOD(sw_collector_db_t, get_sw_id_count, uint32_t,
|
||||
private_sw_collector_db_t *this, bool installed_only)
|
||||
METHOD(sw_collector_db_t, get_sw_id, uint32_t,
|
||||
private_sw_collector_db_t *this, char *name, char **package, char **version,
|
||||
uint8_t *source, bool *installed)
|
||||
{
|
||||
uint32_t count;
|
||||
char *sw_package, *sw_version;
|
||||
uint32_t sw_id = 0, sw_source, sw_installed;
|
||||
enumerator_t *e;
|
||||
|
||||
if (installed_only)
|
||||
/* Does software identifier already exist in database? */
|
||||
e = this->db->query(this->db,
|
||||
"SELECT id, package, version, source, installed "
|
||||
"FROM sw_identifiers WHERE name = ?",
|
||||
DB_TEXT, name, DB_UINT, DB_TEXT, DB_TEXT, DB_UINT, DB_UINT);
|
||||
if (!e)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT COUNT(installed) FROM sw_identifiers WHERE installed = 1 ",
|
||||
DB_UINT);
|
||||
DBG1(DBG_IMC, "database query for sw_identifier failed");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
if (e->enumerate(e, &sw_id, &sw_package, &sw_version, &sw_source,
|
||||
&sw_installed))
|
||||
{
|
||||
if (package)
|
||||
{
|
||||
*package = strdup(sw_package);
|
||||
}
|
||||
if (version)
|
||||
{
|
||||
*version = strdup(sw_version);
|
||||
}
|
||||
if (source)
|
||||
{
|
||||
*source = sw_source;
|
||||
}
|
||||
if (installed)
|
||||
{
|
||||
*installed = sw_installed;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
return sw_id;
|
||||
}
|
||||
|
||||
METHOD(sw_collector_db_t, get_sw_id_count, uint32_t,
|
||||
private_sw_collector_db_t *this, sw_collector_db_query_t type)
|
||||
{
|
||||
uint32_t count, installed;
|
||||
enumerator_t *e;
|
||||
|
||||
if (type == SW_QUERY_ALL)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT COUNT(installed) FROM sw_identifiers", DB_UINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
installed = (type == SW_QUERY_INSTALLED);
|
||||
e = this->db->query(this->db,
|
||||
"SELECT COUNT(installed) FROM sw_identifiers WHERE installed = ?",
|
||||
DB_UINT, installed, DB_UINT);
|
||||
}
|
||||
|
||||
if (!e)
|
||||
{
|
||||
@ -212,23 +256,25 @@ METHOD(sw_collector_db_t, get_sw_id_count, uint32_t,
|
||||
}
|
||||
|
||||
METHOD(sw_collector_db_t, create_sw_enumerator, enumerator_t*,
|
||||
private_sw_collector_db_t *this, bool installed_only)
|
||||
private_sw_collector_db_t *this, sw_collector_db_query_t type)
|
||||
{
|
||||
enumerator_t *e;
|
||||
uint32_t installed;
|
||||
|
||||
if (installed_only)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT name, package, version, installed FROM sw_identifiers "
|
||||
"WHERE installed = 1 ORDER BY name ASC",
|
||||
DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
|
||||
}
|
||||
else
|
||||
if (type == SW_QUERY_ALL)
|
||||
{
|
||||
e = this->db->query(this->db,
|
||||
"SELECT name, package, version, installed FROM sw_identifiers "
|
||||
"ORDER BY name ASC", DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
installed = (type == SW_QUERY_INSTALLED);
|
||||
e = this->db->query(this->db,
|
||||
"SELECT name, package, version, installed FROM sw_identifiers "
|
||||
"WHERE installed = ? ORDER BY name ASC",
|
||||
DB_UINT, installed, DB_TEXT, DB_TEXT, DB_TEXT, DB_UINT);
|
||||
}
|
||||
if (!e)
|
||||
{
|
||||
DBG1(DBG_IMC, "database query for sw_identifier count failed");
|
||||
@ -259,6 +305,7 @@ sw_collector_db_t *sw_collector_db_create(char *uri)
|
||||
.add_event = _add_event,
|
||||
.get_last_event = _get_last_event,
|
||||
.add_sw_event = _add_sw_event,
|
||||
.set_sw_id = _set_sw_id,
|
||||
.get_sw_id = _get_sw_id,
|
||||
.get_sw_id_count = _get_sw_id_count,
|
||||
.create_sw_enumerator = _create_sw_enumerator,
|
||||
@ -296,6 +343,9 @@ sw_collector_db_t *sw_collector_db_create(char *uri)
|
||||
}
|
||||
rng->destroy(rng);
|
||||
|
||||
/* strongTNC workaround - limit epoch to 31 bit unsigned integer */
|
||||
this->epoch &= 0x7fffffff;
|
||||
|
||||
/* Create first event when the OS was installed */
|
||||
first_time = lib->settings->get_str(lib->settings,
|
||||
"sw-collector.first_time", "0000-00-00T00:00:00Z");
|
||||
|
@ -24,6 +24,16 @@
|
||||
#include <library.h>
|
||||
|
||||
typedef struct sw_collector_db_t sw_collector_db_t;
|
||||
typedef enum sw_collector_db_query_t sw_collector_db_query_t;
|
||||
|
||||
/**
|
||||
* Type of software identifier queries
|
||||
*/
|
||||
enum sw_collector_db_query_t {
|
||||
SW_QUERY_ALL,
|
||||
SW_QUERY_INSTALLED,
|
||||
SW_QUERY_DELETED
|
||||
};
|
||||
|
||||
/**
|
||||
* Software collector database object
|
||||
@ -31,7 +41,7 @@ typedef struct sw_collector_db_t sw_collector_db_t;
|
||||
struct sw_collector_db_t {
|
||||
|
||||
/**
|
||||
* Add event to database
|
||||
* bAdd event to database
|
||||
*
|
||||
* @param timestamp Timestamp in 20 octet RFC 3339 format
|
||||
* @return Primary key pointing to event ID or 0 if failed
|
||||
@ -61,35 +71,50 @@ struct sw_collector_db_t {
|
||||
uint8_t action);
|
||||
|
||||
/**
|
||||
* Get software_identifier, creating one if it doesn't exist yet
|
||||
* Set software_identifier, checking if the identifier already exists
|
||||
*
|
||||
* @param name Software identifier
|
||||
* @param package Software package
|
||||
* @param version Version of software package
|
||||
* @param name Software identifier
|
||||
* @param source Source ID of the software collector
|
||||
* @param installed Installation status to be set, TRUE if installed
|
||||
* @param check Check if SW ID is already installed
|
||||
* @return Primary key pointing to SW ID or 0 if failed
|
||||
*/
|
||||
uint32_t (*get_sw_id)(sw_collector_db_t *this, char *package, char *version,
|
||||
char *name, uint8_t source, bool installed, bool check);
|
||||
uint32_t (*set_sw_id)(sw_collector_db_t *this, char *name, char *package,
|
||||
char *version, uint8_t source, bool installed,
|
||||
bool check);
|
||||
|
||||
/**
|
||||
* Get software_identifier record
|
||||
*
|
||||
* @param name Software identifier
|
||||
* @param package Software package
|
||||
* @param version Version of software package
|
||||
* @param source Source ID of the software collector
|
||||
* @param installed Installation status
|
||||
* @return Primary key pointing to SW ID or 0 if failed
|
||||
*/
|
||||
uint32_t (*get_sw_id)(sw_collector_db_t *this, char *name, char **package,
|
||||
char **version, uint8_t *source, bool *installed);
|
||||
|
||||
/**
|
||||
* Get number of installed or deleted software identifiers
|
||||
*
|
||||
* @param installed_only Count installed SW IDs if TRUE
|
||||
* @return Count
|
||||
* @param type Query type (ALL, INSTALLED, DELETED)
|
||||
* @return Count
|
||||
*/
|
||||
uint32_t (*get_sw_id_count)(sw_collector_db_t *this, bool installed_only);
|
||||
uint32_t (*get_sw_id_count)(sw_collector_db_t *this,
|
||||
sw_collector_db_query_t type);
|
||||
|
||||
/**
|
||||
* Enumerate over all collected [installed] software identities
|
||||
*
|
||||
* @param installed_only Return only installed software identities
|
||||
* @return Enumerator
|
||||
* @param type Query type (ALL, INSTALLED, DELETED)
|
||||
* @return Enumerator
|
||||
*/
|
||||
enumerator_t* (*create_sw_enumerator)(sw_collector_db_t *this,
|
||||
bool installed_only);
|
||||
sw_collector_db_query_t type);
|
||||
|
||||
/**
|
||||
* Destroy sw_collector_db_t object
|
||||
|
@ -44,6 +44,11 @@ struct private_sw_collector_history_t {
|
||||
*/
|
||||
char *os;
|
||||
|
||||
/**
|
||||
* Product string 'name version arch'
|
||||
*/
|
||||
char *product;
|
||||
|
||||
/**
|
||||
* OS info about endpoint
|
||||
*/
|
||||
@ -61,6 +66,16 @@ struct private_sw_collector_history_t {
|
||||
|
||||
};
|
||||
|
||||
METHOD(sw_collector_history_t, get_os, char*,
|
||||
private_sw_collector_history_t *this, char **product)
|
||||
{
|
||||
if (product)
|
||||
{
|
||||
*product = this->product;
|
||||
}
|
||||
return this->os;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define auxiliary package_t list item object
|
||||
*/
|
||||
@ -277,7 +292,14 @@ METHOD(sw_collector_history_t, extract_packages, bool,
|
||||
goto end;
|
||||
}
|
||||
|
||||
sw_id = this->db->get_sw_id(this->db, p->package, p->version, p->sw_id,
|
||||
/* packages without version information cannot be handled */
|
||||
if (strlen(p->version) == 0)
|
||||
{
|
||||
free_package(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
sw_id = this->db->set_sw_id(this->db, p->sw_id, p->package, p->version,
|
||||
this->source, op != SW_OP_REMOVE, FALSE);
|
||||
if (!sw_id)
|
||||
{
|
||||
@ -291,8 +313,9 @@ METHOD(sw_collector_history_t, extract_packages, bool,
|
||||
|
||||
if (op == SW_OP_UPGRADE)
|
||||
{
|
||||
sw_id = this->db->get_sw_id(this->db, p->package, p->old_version,
|
||||
p->old_sw_id, this->source, FALSE, FALSE);
|
||||
sw_id = this->db->set_sw_id(this->db, p->old_sw_id, p->package,
|
||||
p->old_version, this->source, FALSE,
|
||||
FALSE);
|
||||
if (!sw_id)
|
||||
{
|
||||
goto end;
|
||||
@ -376,7 +399,7 @@ METHOD(sw_collector_history_t, merge_installed_packages, bool,
|
||||
name = create_sw_id(this->tag_creator, this->os, package, version);
|
||||
DBG3(DBG_IMC, " %s merged", name);
|
||||
|
||||
sw_id = this->db->get_sw_id(this->db, package, version, name,
|
||||
sw_id = this->db->set_sw_id(this->db, name, package, version,
|
||||
this->source, TRUE, TRUE);
|
||||
free(name);
|
||||
if (!sw_id)
|
||||
@ -387,7 +410,7 @@ METHOD(sw_collector_history_t, merge_installed_packages, bool,
|
||||
}
|
||||
success = TRUE;
|
||||
DBG1(DBG_IMC, " merged %u installed packages, %u registed in database",
|
||||
count, this->db->get_sw_id_count(this->db, TRUE));
|
||||
count, this->db->get_sw_id_count(this->db, SW_QUERY_INSTALLED));
|
||||
|
||||
end:
|
||||
pclose(file);
|
||||
@ -399,6 +422,7 @@ METHOD(sw_collector_history_t, destroy, void,
|
||||
{
|
||||
this->os_info->destroy(this->os_info);
|
||||
free(this->os);
|
||||
free(this->product);
|
||||
free(this);
|
||||
}
|
||||
|
||||
@ -414,6 +438,7 @@ sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db,
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_os = _get_os,
|
||||
.extract_timestamp = _extract_timestamp,
|
||||
.extract_packages = _extract_packages,
|
||||
.merge_installed_packages = _merge_installed_packages,
|
||||
@ -423,7 +448,7 @@ sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db,
|
||||
.source = source,
|
||||
.os_info = imc_os_info_create(),
|
||||
.tag_creator = lib->settings->get_str(lib->settings,
|
||||
"sw-collector.tag_creator", "strongswan.org"),
|
||||
"%s.tag_creator.regid", "strongswan.org", lib->ns),
|
||||
);
|
||||
|
||||
os_type = this->os_info->get_type(this->os_info);
|
||||
@ -445,6 +470,8 @@ sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db,
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* construct OS string */
|
||||
if (asprintf(&this->os, "%.*s_%.*s-%.*s", os_name.len, os_name.ptr,
|
||||
os_version.len, os_version.ptr,
|
||||
os_arch.len, os_arch.ptr) == -1)
|
||||
@ -454,5 +481,15 @@ sw_collector_history_t *sw_collector_history_create(sw_collector_db_t *db,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* construct product string */
|
||||
if (asprintf(&this->product, "%.*s %.*s %.*s", os_name.len, os_name.ptr,
|
||||
os_version.len, os_version.ptr,
|
||||
os_arch.len, os_arch.ptr) == -1)
|
||||
{
|
||||
DBG1(DBG_IMC, "constructon of product string failed");
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
@ -44,6 +44,14 @@ enum sw_collector_history_op_t {
|
||||
*/
|
||||
struct sw_collector_history_t {
|
||||
|
||||
/**
|
||||
* Get OS and product strings
|
||||
*
|
||||
* @param product Product string formed from OS info
|
||||
* @return OS string formed from OS info
|
||||
*/
|
||||
char* (*get_os)(sw_collector_history_t *this, char **product);
|
||||
|
||||
/**
|
||||
* Extract timestamp from event in installation history
|
||||
*
|
||||
|
@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "sw_collector_rest_api.h"
|
||||
|
||||
#include <rest/rest.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_sw_collector_rest_api_t private_sw_collector_rest_api_t;
|
||||
|
||||
/**
|
||||
* Private data of an sw_collector_rest_api_t object.
|
||||
*/
|
||||
struct private_sw_collector_rest_api_t {
|
||||
|
||||
/**
|
||||
* Public members of sw_collector_rest_api_state_t
|
||||
*/
|
||||
sw_collector_rest_api_t public;
|
||||
|
||||
/**
|
||||
* Software collector database
|
||||
*/
|
||||
sw_collector_db_t *db;
|
||||
|
||||
/**
|
||||
* REST API of central collector database
|
||||
*/
|
||||
rest_t *rest_api;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Put all locally retrieved software identifiers into a json object
|
||||
*/
|
||||
static json_object* create_rest_request(private_sw_collector_rest_api_t *this,
|
||||
sw_collector_db_query_t type)
|
||||
{
|
||||
json_object *jrequest, *jarray, *jstring;
|
||||
char *name, *package, *version;
|
||||
uint32_t i;
|
||||
enumerator_t *e;
|
||||
|
||||
jrequest = json_object_new_object();
|
||||
jarray = json_object_new_array();
|
||||
json_object_object_add(jrequest, "data", jarray);
|
||||
|
||||
e = this->db->create_sw_enumerator(this->db, type);
|
||||
if (!e)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
while (e->enumerate(e, &name, &package, &version, &i))
|
||||
{
|
||||
jstring = json_object_new_string(name);
|
||||
json_object_array_add(jarray, jstring);
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
return jrequest;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
/** public enumerator interface */
|
||||
enumerator_t public;
|
||||
/** enumerated json array */
|
||||
json_object *jarray;
|
||||
/** current index +1, initialized at 0 */
|
||||
int idx;
|
||||
} json_array_enumerator_t;
|
||||
|
||||
METHOD(enumerator_t, enumerate, bool,
|
||||
json_array_enumerator_t *this, va_list args)
|
||||
{
|
||||
json_object *jvalue;
|
||||
char **out;
|
||||
|
||||
VA_ARGS_VGET(args, out);
|
||||
|
||||
if (this->idx >= json_object_array_length(this->jarray))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
jvalue = json_object_array_get_idx(this->jarray, this->idx++);
|
||||
if (json_object_get_type(jvalue) != json_type_string)
|
||||
{
|
||||
DBG1(DBG_IMC, "json_string element expected in json_array");
|
||||
return FALSE;
|
||||
}
|
||||
*out = (char*)json_object_get_string(jvalue);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(enumerator_t, enumerator_destroy, void,
|
||||
json_array_enumerator_t *this)
|
||||
{
|
||||
json_object_put(this->jarray);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(sw_collector_rest_api_t, create_sw_enumerator, enumerator_t*,
|
||||
private_sw_collector_rest_api_t *this, sw_collector_db_query_t type)
|
||||
{
|
||||
json_array_enumerator_t *enumerator;
|
||||
json_object *jrequest, *jresponse;
|
||||
char cmd[BUF_LEN];
|
||||
status_t status;
|
||||
|
||||
jrequest = create_rest_request(this, type);
|
||||
if (!jrequest)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
snprintf(cmd, BUF_LEN, "sessions/0/swid-measurement/");
|
||||
|
||||
status = this->rest_api->post(this->rest_api, cmd, jrequest, &jresponse);
|
||||
json_object_put(jrequest);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case SUCCESS:
|
||||
case NOT_FOUND:
|
||||
jresponse = json_object_new_array();
|
||||
break;
|
||||
case NEED_MORE:
|
||||
if (json_object_get_type(jresponse) != json_type_array)
|
||||
{
|
||||
DBG1(DBG_IMC, "REST response was not a json_array");
|
||||
json_object_put(jresponse);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
case FAILED:
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(enumerator,
|
||||
.public = {
|
||||
.enumerate = enumerator_enumerate_default,
|
||||
.venumerate = _enumerate,
|
||||
.destroy = _enumerator_destroy,
|
||||
},
|
||||
.jarray = jresponse,
|
||||
);
|
||||
|
||||
return &enumerator->public;
|
||||
}
|
||||
|
||||
METHOD(sw_collector_rest_api_t, destroy, void,
|
||||
private_sw_collector_rest_api_t *this)
|
||||
{
|
||||
this->rest_api->destroy(this->rest_api);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
sw_collector_rest_api_t *sw_collector_rest_api_create(sw_collector_db_t *db)
|
||||
{
|
||||
private_sw_collector_rest_api_t *this;
|
||||
int timeout;
|
||||
char *uri;
|
||||
|
||||
uri = lib->settings->get_str(lib->settings, "%s.rest_api.uri", NULL,
|
||||
lib->ns);
|
||||
timeout = lib->settings->get_int(lib->settings, "%s.rest_api.timeout", 120,
|
||||
lib->ns);
|
||||
if (!uri)
|
||||
{
|
||||
DBG1(DBG_IMC, "REST URI to central collector database not set");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.create_sw_enumerator = _create_sw_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.db = db,
|
||||
.rest_api = rest_create(uri, timeout),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* 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. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sw_collector_rest_api_t sw_collector_rest_api
|
||||
* @{ @ingroup imc_swima
|
||||
*/
|
||||
|
||||
#ifndef SW_COLLECTOR_REST_API_H_
|
||||
#define SW_COLLECTOR_REST_API_H_
|
||||
|
||||
#include "sw_collector_db.h"
|
||||
|
||||
typedef struct sw_collector_rest_api_t sw_collector_rest_api_t;
|
||||
|
||||
/**
|
||||
* Software collector database object
|
||||
*/
|
||||
struct sw_collector_rest_api_t {
|
||||
|
||||
/**
|
||||
* List of locally stored software identifiers that are not registered
|
||||
* in a central collector database
|
||||
*
|
||||
* @param type Query type (ALL, INSTALLED, DELETED)
|
||||
* @return Enumerator
|
||||
*/
|
||||
enumerator_t* (*create_sw_enumerator)(sw_collector_rest_api_t *this,
|
||||
sw_collector_db_query_t type);
|
||||
|
||||
/**
|
||||
* Destroy sw_collector_rest_api_t object
|
||||
*/
|
||||
void (*destroy)(sw_collector_rest_api_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an sw_collector_rest_api_t instance
|
||||
*
|
||||
* @param db Software collector database to be used
|
||||
*/
|
||||
sw_collector_rest_api_t* sw_collector_rest_api_create(sw_collector_db_t *db);
|
||||
|
||||
#endif /** SW_COLLECTOR_REST_API_H_ @}*/
|
Loading…
x
Reference in New Issue
Block a user