sw-collector: Added --full option
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 31 Jul 2017 15:21:03 +0000 (17:21 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 3 Aug 2017 07:02:54 +0000 (09:02 +0200)
conf/options/sw-collector.opt
src/sw-collector/sw-collector.8.in
src/sw-collector/sw-collector.c

index dff5716..3cd714f 100644 (file)
@@ -28,5 +28,8 @@ sw-collector.tag_creator.name = strongSwan Project
 sw-collector.tag_creator.regid = strongswan.org
        regid of the tagCreator entity.
 
+sw-collector.swid_generator = /usr/local/bin/swid_generator
+       SWID generator command to be executed.
+
 sw-collector.load =
        Plugins to load in sw-collector tool.
index e542122..da713cd 100644 (file)
@@ -16,7 +16,15 @@ sw-collector \- Extracts software installation events from dpkg history log
 .OP \-\-debug level
 .OP \-\-quiet
 .OP \-\-installed\fR|\fB\--removed
-.BR \-\-list |\fB\-\-unregistered\fR|\fB\-\-generate
+.BR \-\-list |\fB\-\-unregistered
+.YS
+.
+.SY "sw-collector"
+.OP \-\-debug level
+.OP \-\-quiet
+.OP \-\-installed\fR|\fB\--removed
+.OP \-\-full
+.BR \-\-generate
 .YS
 .
 .SY "sw-collector"
@@ -57,6 +65,10 @@ Apply command to installed software packages, only.
 .B "\-r, \-\-removed
 Apply command to removed software packages, only.
 .TP
+.B "\-f, \-\-full
+Generate ISO 19770-2:2015 SWID tags with full file information (possible for
+installed software packages, only).
+.TP
 .B "\-l, \-\-list
 Lists all software packages stored in the collector database showing their
 installation status.
@@ -67,8 +79,8 @@ which no SWID tags exist yet in a central collector database reachable via a
 REST interface. 
 .TP
 .B "\-g, \-\-generate
-Generates minimal SWID tags for all software packages residing in the local
-collector database but for which no SWID tags exist in a central collector
+Generates ISO 19770-2:2015 SWID tags for all software packages residing in the
+local collector database but for which no SWID tags exist in a central collector
 database reachable via a REST interface.
 .TP
 .B "\-m, \-\-migrate
index bb39396..0bdd598 100644 (file)
 #include "sw_collector_dpkg.h"
 #
 #include <library.h>
+#include <bio/bio_writer.h>
 #include <utils/debug.h>
 #include <utils/lexparser.h>
 
 #include <imv/imv_os_info.h>
 
+#define SWID_GENERATOR "/usr/local/bin/swid_generator"
+
 /**
  * global debug output variables
  */
@@ -117,18 +120,20 @@ Usage:\n\
   sw-collector --help\n\
   sw-collector [--debug <level>] [--quiet] [--count <event count>]\n\
   sw-collector [--debug <level>] [--quiet] [--installed|--removed] \
---list|-unregistered|--generate\n\
+--list|-unregistered\n\
+  sw-collector [--debug <level>] [--quiet] [--installed|--removed] \
+[--full] --generate\n\
   sw-collector [--debug <level>] [--quiet] --migrate\n");
 }
 
 /**
  * Parse command line options
  */
-static collector_op_t do_args(int argc, char *argv[],
+static collector_op_t do_args(int argc, char *argv[], bool *full_tags,
                                                          sw_collector_db_query_t *query_type)
 {
        collector_op_t op = COLLECTOR_OP_EXTRACT;
-       bool installed = FALSE, removed = FALSE;
+       bool installed = FALSE, removed = FALSE, full = FALSE;
 
        /* reinit getopt state */
        optind = 0;
@@ -141,6 +146,7 @@ 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' },
+                       { "full", no_argument, NULL, 'f' },
                        { "generate", no_argument, NULL, 'g' },
                        { "installed", no_argument, NULL, 'i' },
                        { "list", no_argument, NULL, 'l' },
@@ -151,7 +157,7 @@ static collector_op_t do_args(int argc, char *argv[],
                        { 0,0,0,0 }
                };
 
-               c = getopt_long(argc, argv, "hc:d:gilmqru", long_opts, NULL);
+               c = getopt_long(argc, argv, "hc:d:fgilmqru", long_opts, NULL);
                switch (c)
                {
                        case EOF:
@@ -166,6 +172,9 @@ static collector_op_t do_args(int argc, char *argv[],
                        case 'd':
                                debug_level = atoi(optarg);
                                continue;
+                       case 'f':
+                               full = TRUE;
+                               continue;
                        case 'g':
                                op = COLLECTOR_OP_GENERATE;
                                continue;
@@ -193,6 +202,7 @@ static collector_op_t do_args(int argc, char *argv[],
                }
                break;
        }
+
        if ((!installed && !removed) || (installed && removed))
        {
                *query_type = SW_QUERY_ALL;
@@ -205,6 +215,8 @@ static collector_op_t do_args(int argc, char *argv[],
        {
                *query_type = SW_QUERY_REMOVED;
        }
+       *full_tags = full;
+
        return op;
 }
 
@@ -458,31 +470,81 @@ static int unregistered_identifiers(sw_collector_db_t *db,
 }
 
 /**
- * Generate a minimalistic ISO 19770-2:2015 SWID tag
+ * Generate a either a full or 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* entity, char *regid, char *product,
+                                                 bool full_tag, char *generator)
 {
-       char *tag_id, *tag;
-       int res;
+       char *tag = NULL;
 
-       tag_id = strstr(name, "__");
-       if (!tag_id)
+       if (full_tag)
        {
-               return NULL;
+               size_t tag_buf_len = 8192;
+               char tag_buf[tag_buf_len], command[BUF_LEN];
+               bio_writer_t *writer;
+               chunk_t tag_chunk;
+               FILE *file;
+
+               /* Compose the SWID generator command */
+               snprintf(command, BUF_LEN, "%s swid --full --regid %s --entity-name "
+                                "\"%s\" --package %s", generator, regid, entity, package);
+\
+               /* Open a pipe stream for reading the SWID generator output */
+               file = popen(command, "r");
+               if (file)
+               {
+                       writer = bio_writer_create(tag_buf_len);
+                       while (TRUE)
+                       {
+                               if (!fgets(tag_buf, tag_buf_len, file))
+                               {
+                                       break;
+                               }
+                               writer->write_data(writer,
+                                                                  chunk_create(tag_buf, strlen(tag_buf)));
+                       }
+                       pclose(file);
+                       tag_chunk = writer->extract_buf(writer);
+                       writer->destroy(writer);
+                       if (tag_chunk.len > 1)
+                       {
+                               tag = tag_chunk.ptr;
+                               tag[tag_chunk.len - 1] = '\0';
+                       }
+               }
+               else
+               {
+                       DBG1(DBG_IMC, "failed to run swid_generator command");
+               }
        }
-       tag_id += 2;
 
-       res = asprintf(&tag, "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+       /* Generate minimalistic SWID tag */
+       if (!tag)
+       {
+               char *tag_id;
+
+               tag_id = strstr(name, "__");
+               if (!tag_id)
+               {
+                       return NULL;
+               }
+               tag_id += 2;
+
+               if (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);
+                        package, tag_id, version, entity, regid, product) == -1)
+               {
+                       tag = NULL;
+               }
+       }
 
-       return (res == -1) ? NULL : tag;
+       return tag;
 }
 
 /**
@@ -490,10 +552,10 @@ static char* generate_tag(char *name, char *package, char *version,
  * all removed SW identifiers that are not registered centrally
  */
 static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
-                                                sw_collector_db_query_t type)
+                                                bool full_tags, sw_collector_db_query_t type)
 {
        sw_collector_rest_api_t *rest_api;
-       char *name, *package, *version, *entity, *regid, *product, *tag;
+       char *name, *package, *version, *entity, *regid, *product, *generator, *tag;
        enumerator_t *enumerator;
        uint32_t sw_id;
        bool installed;
@@ -503,6 +565,8 @@ static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
                                                                        "strongSwan Project", lib->ns);
        regid  = lib->settings->get_str(lib->settings, "%s.tag_creator.regid",
                                                                        "strongswan.org", lib->ns);
+       generator = lib->settings->get_str(lib->settings, "%s.swid_generator",
+                                                                       SWID_GENERATOR, lib->ns);
        info->get_os(info, &product);
 
        rest_api = sw_collector_rest_api_create(db);
@@ -521,9 +585,11 @@ static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
                sw_id = db->get_sw_id(db, name, &package, &version, NULL, &installed);
                if (sw_id)
                {
-                       tag = generate_tag(name, package, version, entity, regid, product);
+                       tag = generate_tag(name, package, version, entity, regid, product,
+                                                          full_tags && installed, generator);
                        if (tag)
                        {
+                               DBG2(DBG_IMC, "  creating %s", name);
                                printf("%s\n", tag);
                                free(tag);
                                count++;
@@ -542,16 +608,16 @@ static int generate_tags(sw_collector_info_t *info, sw_collector_db_t *db,
        switch (type)
        {
                case SW_QUERY_ALL:
-                       DBG1(DBG_IMC, "%d tags for unregistered software identifiers with "
-                                "%d installed and %d removed", count, installed_count,
-                                count - installed_count);
+                       DBG1(DBG_IMC, "created %d tags for unregistered software "
+                                "identifiers with %d installed and %d removed", count,
+                                installed_count,  count - installed_count);
                        break;
                case SW_QUERY_INSTALLED:
-                       DBG1(DBG_IMC, "%d tags for unregistered installed software "
+                       DBG1(DBG_IMC, "created %d tags for unregistered installed software "
                                 "identifiers", count);
                        break;
                case SW_QUERY_REMOVED:
-                       DBG1(DBG_IMC, "%d tags for unregistered removed software "
+                       DBG1(DBG_IMC, "created %d tags for unregistered removed software "
                                 "identifiers", count);
                        break;
        }
@@ -615,10 +681,11 @@ int main(int argc, char *argv[])
        sw_collector_db_query_t query_type;
        sw_collector_info_t *info;
        collector_op_t op;
+       bool full_tags;
        char *uri, *tag_creator;
        int status = EXIT_FAILURE;
 
-       op = do_args(argc, argv, &query_type);
+       op = do_args(argc, argv, &full_tags, &query_type);
 
        /* enable sw_collector debugging hook */
        dbg = sw_collector_dbg;
@@ -672,7 +739,7 @@ int main(int argc, char *argv[])
                        status = unregistered_identifiers(db, query_type);
                        break;
                case COLLECTOR_OP_GENERATE:
-                       status = generate_tags(info, db, query_type);
+                       status = generate_tags(info, db, full_tags, query_type);
                        break;
                case COLLECTOR_OP_MIGRATE:
                        status = migrate(info, db);