Blob Blame History Raw
From c25092c8a9b5fa42cd5388313b1db4d8ad81034f Mon Sep 17 00:00:00 2001
From: Jakub Filak <jfilak@redhat.com>
Date: Tue, 16 Sep 2014 13:34:28 +0200
Subject: [LIBREPORT PATCH 83/93] rhtsupport: submit ureport and attach case ID
 to ureport

ABRT Server for RHEL provides an authenticated way of uReport
submission. The authentication can be done via client certificates or
HTTP Basic auth. ABRT client uses the client certificates for
Auto-reporting, but when user wants to report a problem manually he
needs to have special permissions to work with the certificates or he
cannot use this way of authentication. Fortunately, RHEL ABRT Server can
authenticate user via RHTSupport user name an password, but we don't
want to ask users to provide/configure the Customer Portal credentials
twice, hence we will attach a case ID to a bthash from
reporter-rhtsupport.

This commit also addresses complaints about no evidences of sending
uReport to ABRT Server. This commit adds a log message
"Sending ABRT crash statistics data".

Relate to rhbz#1139987, rhbz#1084028

Signed-off-by: Jakub Filak <jfilak@redhat.com>
---
 doc/reporter-rhtsupport.txt       |  18 +++++-
 src/include/ureport.h             |  13 +++-
 src/lib/ureport.c                 |  13 +++-
 src/plugins/reporter-rhtsupport.c | 121 +++++++++++++++++++++++++++++++++++++-
 src/plugins/reporter-ureport.c    |   2 +-
 5 files changed, 162 insertions(+), 5 deletions(-)

diff --git a/doc/reporter-rhtsupport.txt b/doc/reporter-rhtsupport.txt
index b018906..c4aa459 100644
--- a/doc/reporter-rhtsupport.txt
+++ b/doc/reporter-rhtsupport.txt
@@ -7,7 +7,7 @@ reporter-rhtsupport - Reports problem to RHTSupport.
 
 SYNOPSIS
 --------
-'reporter-rhtsupport' [-v] [-c CONFFILE] -d DIR
+'reporter-rhtsupport' [-v] [-c CONFFILE] [-u -C UR_CONFFILE] -d DIR
 
 Or:
 
@@ -18,6 +18,9 @@ DESCRIPTION
 The tool reads problem directory DIR. Then it logs in to RHTSupport
 and creates a new case.
 
+The tool can be configured to submit an uReport to RHTSupport together with
+creating a new case.
+
 The URL to new case is printed to stdout and recorded in 'reported_to'
 element in DIR.
 
@@ -30,6 +33,9 @@ If problem data in DIR was never reported to RHTSupport, upload will fail.
 Option -tCASE uploads FILEs to the case CASE on RHTSupport site.
 -d DIR is ignored.
 
+Option -u uploads uReport along with creating a new case. uReport configuration
+is loaded from UR_CONFFILE which defaults to
+/etc/libreport/plugins/ureport.conf.
 
 Configuration file
 ~~~~~~~~~~~~~~~~~~
@@ -47,6 +53,10 @@ Configuration file lines should have 'PARAM = VALUE' format. The parameters are:
 'SSLVerify'::
 	Use yes/true/on/1 to verify server's SSL certificate. (default: yes)
 
+'SubmitUReport'::
+	Use yes/true/on/1 to enable submitting uReport together wit creating a new
+	case. (default: no)
+
 Parameters can be overridden via $RHTSupport_PARAM environment variables.
 
 Integration with ABRT events
@@ -71,6 +81,12 @@ OPTIONS
 -t[ID]::
    Upload FILEs to the already created case on RHTSupport site.
 
+-u::
+   Submit uReport together with creating a new case.
+
+-C UR_CONFFILE::
+   Configuration file for submitting uReports.
+
 FILES
 -----
 /usr/share/libreport/conf.d/plugins/rhtsupport.conf::
diff --git a/src/include/ureport.h b/src/include/ureport.h
index 3ee12cd..8bb1f6c 100644
--- a/src/include/ureport.h
+++ b/src/include/ureport.h
@@ -47,7 +47,7 @@ struct ureport_preferences
  */
 struct ureport_server_config
 {
-    const char *ur_url;   ///< Web service URL
+    char *ur_url;         ///< Web service URL
     bool ur_ssl_verify;   ///< Verify HOST and PEER certificates
     char *ur_client_cert; ///< Path to certificate used for client
                           ///< authentication (or NULL)
@@ -91,6 +91,17 @@ ureport_server_config_load(struct ureport_server_config *config,
                            map_string_t *settings);
 
 /*
+ * Configure HTTP(S) URL to server's index page
+ *
+ * @param config Where the url is stored
+ * @param server_url Index URL
+ */
+#define ureport_server_config_set_url libreport_ureport_server_config_set_url
+void
+ureport_server_config_set_url(struct ureport_server_config *config,
+                              char *server_url);
+
+/*
  * Configure client certificate paths
  *
  * @param config Where the paths are stored
diff --git a/src/lib/ureport.c b/src/lib/ureport.c
index 5453a37..26f3562 100644
--- a/src/lib/ureport.c
+++ b/src/lib/ureport.c
@@ -62,6 +62,14 @@ error:
 }
 
 void
+ureport_server_config_set_url(struct ureport_server_config *config,
+                              char *server_url)
+{
+    free(config->ur_url);
+    config->ur_url = server_url;
+}
+
+void
 ureport_server_config_set_client_auth(struct ureport_server_config *config,
                                       const char *client_auth)
 {
@@ -211,7 +219,7 @@ void
 ureport_server_config_load(struct ureport_server_config *config,
                            map_string_t *settings)
 {
-    UREPORT_OPTION_VALUE_FROM_CONF(settings, "URL", config->ur_url, (const char *));
+    UREPORT_OPTION_VALUE_FROM_CONF(settings, "URL", config->ur_url, xstrdup);
     UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLVerify", config->ur_ssl_verify, string_to_bool);
 
     bool include_auth = false;
@@ -248,6 +256,9 @@ ureport_server_config_init(struct ureport_server_config *config)
 void
 ureport_server_config_destroy(struct ureport_server_config *config)
 {
+    free(config->ur_url);
+    config->ur_url = DESTROYED_POINTER;
+
     free(config->ur_client_cert);
     config->ur_client_cert = DESTROYED_POINTER;
 
diff --git a/src/plugins/reporter-rhtsupport.c b/src/plugins/reporter-rhtsupport.c
index 55bcda6..cd72c87 100644
--- a/src/plugins/reporter-rhtsupport.c
+++ b/src/plugins/reporter-rhtsupport.c
@@ -17,6 +17,7 @@
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 #include <libtar.h>
+#include "ureport.h"
 #include "internal_libreport.h"
 #include "client.h"
 #include "libreport_curl.h"
@@ -169,6 +170,51 @@ ret_clean:
 }
 
 static
+char *submit_ureport(const char *dump_dir_name, struct ureport_server_config *conf)
+{
+    struct dump_dir *dd = dd_opendir(dump_dir_name, DD_OPEN_READONLY);
+    if (dd == NULL)
+        return NULL;
+
+    report_result_t *rr_bthash = find_in_reported_to(dd, "uReport");
+    dd_close(dd);
+
+    if (rr_bthash != NULL)
+    {
+        log_notice("uReport has already been submitted.");
+        char *ret = xstrdup(rr_bthash->bthash);
+        free_report_result(rr_bthash);
+        return ret;
+    }
+
+    char *json = ureport_from_dump_dir(dump_dir_name);
+    if (json == NULL)
+        return NULL;
+
+    struct ureport_server_response *resp = ureport_submit(json, conf);
+    free(json);
+    if (resp == NULL)
+        return NULL;
+
+    char *bthash = NULL;
+    if (!resp->urr_is_error)
+    {
+        if (resp->urr_bthash != NULL)
+            bthash = xstrdup(resp->urr_bthash);
+
+        ureport_server_response_save_in_dump_dir(resp, dump_dir_name, conf);
+
+        if (resp->urr_message)
+            log(resp->urr_message);
+    }
+    else if (g_verbose > 2)
+        error_msg(_("Server responded with an error: '%s'"), resp->urr_value);
+
+    ureport_server_response_free(resp);
+    return bthash;
+}
+
+static
 char *ask_rh_login(const char *message)
 {
     char *login = ask(message);
@@ -203,6 +249,40 @@ char *get_param_string(const char *name, map_string_t *settings, const char *dfl
     return xstrdup(envvar ? envvar : (get_map_string_item_or_NULL(settings, name) ? : dflt));
 }
 
+static
+void prepare_ureport_configuration(const char *urcfile,
+        map_string_t *settings, struct ureport_server_config *urconf,
+        const char *portal_url, const char *login, const char *password, bool ssl_verify)
+{
+    load_conf_file(urcfile, settings, false);
+    ureport_server_config_init(urconf);
+
+    char *url = NULL;
+    UREPORT_OPTION_VALUE_FROM_CONF(settings, "URL", url, xstrdup);
+    if (url == NULL)
+    {
+        ureport_server_config_set_url(urconf, concat_path_file(portal_url, "/telemetry/abrt"));
+        urconf->ur_ssl_verify = ssl_verify;
+    }
+    else
+    {
+        UREPORT_OPTION_VALUE_FROM_CONF(settings, "SSLVerify", urconf->ur_ssl_verify, string_to_bool);
+        ureport_server_config_set_url(urconf, url);
+    }
+
+    ureport_server_config_set_basic_auth(urconf, login, password);
+
+    bool include_auth = true;
+    UREPORT_OPTION_VALUE_FROM_CONF(settings, "IncludeAuthData", include_auth, string_to_bool);
+
+    if (include_auth)
+    {
+        const char *auth_items = NULL;
+        UREPORT_OPTION_VALUE_FROM_CONF(settings, "AuthDataItems", auth_items, (const char *));
+        urconf->ur_prefs.urp_auth_items = parse_list(auth_items);
+    }
+}
+
 int main(int argc, char **argv)
 {
     abrt_init(argv);
@@ -217,13 +297,14 @@ int main(int argc, char **argv)
     const char *dump_dir_name = ".";
     const char *case_no = NULL;
     GList *conf_file = NULL;
+    const char *urconf_file = UREPORT_CONF_FILE_PATH;
 
     /* Can't keep these strings/structs static: _() doesn't support that */
     const char *program_usage_string = _(
         "\n"
         "& [-v] [-c CONFFILE] -d DIR\n"
         "or:\n"
-        "& [-v] [-c CONFFILE] [-d DIR] -t[ID] FILE...\n"
+        "& [-v] [-c CONFFILE] [-d DIR] -t[ID] [-u -C UR_CONFFILE] FILE...\n"
         "\n"
         "Reports a problem to RHTSupport.\n"
         "\n"
@@ -240,6 +321,10 @@ int main(int argc, char **argv)
         "\n"
         "Option -tCASE uploads FILEs to the case CASE on RHTSupport site.\n"
         "-d DIR is ignored."
+        "\n"
+        "Option -u sends ABRT crash statistics data (uReport) before creating a new case.\n"
+        "uReport configuration is loaded from UR_CONFFILE which defaults to\n"
+        UREPORT_CONF_FILE_PATH".\n"
     );
     enum {
         OPT_v = 1 << 0,
@@ -247,6 +332,7 @@ int main(int argc, char **argv)
         OPT_c = 1 << 2,
         OPT_t = 1 << 3,
         OPT_f = 1 << 4,
+        OPT_u = 1 << 5,
     };
     /* Keep enum above and order of options below in sync! */
     struct options program_options[] = {
@@ -255,6 +341,8 @@ int main(int argc, char **argv)
         OPT_LIST(     'c', NULL, &conf_file    , "FILE", _("Configuration file (may be given many times)")),
         OPT_OPTSTRING('t', NULL, &case_no      , "ID"  , _("Upload FILEs [to case with this ID]")),
         OPT_BOOL(     'f', NULL, NULL          ,         _("Force reporting even if this problem is already reported")),
+        OPT_BOOL(     'u', NULL, NULL          ,         _("Submit uReport before creating a new case")),
+        OPT_STRING(   'C', NULL, &urconf_file  , "FILE", _("Configuration file for uReport")),
         OPT_END()
     };
     unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
@@ -303,6 +391,12 @@ int main(int argc, char **argv)
                 /* RH has a 250m limit for web attachments (as of 2013) */
                 envvar ? envvar : (get_map_string_item_or_NULL(settings, "BigSizeMB") ? : "200")
     );
+    envvar = getenv("RHTSupport_SubmitUReport");
+    bool submit_ur = string_to_bool(
+                envvar ? envvar :
+                    (get_map_string_item_or_NULL(settings, "SubmitUReport") ? :
+                        ((opts & OPT_u) ? "1" : "0"))
+    );
     free_map_string(settings);
 
     char *base_api_url = xstrdup(url);
@@ -484,6 +578,21 @@ int main(int argc, char **argv)
 
     if (!(opts & OPT_t))
     {
+        char *bthash = NULL;
+
+        map_string_t *ursettings = new_map_string();
+        struct ureport_server_config urconf;
+
+        prepare_ureport_configuration(urconf_file, ursettings, &urconf,
+                url, login, password, ssl_verify);
+
+        if (submit_ur)
+        {
+            log(_("Sending ABRT crash statistics data"));
+
+            bthash = submit_ureport(dump_dir_name, &urconf);
+        }
+
         log(_("Creating a new case"));
 
         char *product = NULL;
@@ -555,10 +664,20 @@ int main(int argc, char **argv)
         }
         /* else: error msg was already emitted by dd_opendir */
 
+        if (bthash)
+        {
+            log(_("Linking ABRT crash statistics record with the case"));
+            ureport_attach_string(bthash, "RHCID", result->url, &urconf);
+        }
+
         url = result->url;
         result->url = NULL;
         free_rhts_result(result);
         result = NULL;
+
+        ureport_server_config_destroy(&urconf);
+        free_map_string(ursettings);
+        free(bthash);
     }
 
     char *remote_filename = NULL;
diff --git a/src/plugins/reporter-ureport.c b/src/plugins/reporter-ureport.c
index 7bd3fb3..06b5341 100644
--- a/src/plugins/reporter-ureport.c
+++ b/src/plugins/reporter-ureport.c
@@ -100,7 +100,7 @@ int main(int argc, char **argv)
     ureport_server_config_load(&config, settings);
 
     if (opts & OPT_u)
-        config.ur_url = arg_server_url;
+        ureport_server_config_set_url(&config, xstrdup(arg_server_url));
     if (opts & OPT_k)
         config.ur_ssl_verify = !insecure;
     if (opts & OPT_t)
-- 
1.8.3.1