diff --git a/auditbeat/auditbeat.reference.yml b/auditbeat/auditbeat.reference.yml index 999e6676bf3..0c54c87fb71 100644 --- a/auditbeat/auditbeat.reference.yml +++ b/auditbeat/auditbeat.reference.yml @@ -722,8 +722,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template ===================================== diff --git a/filebeat/filebeat.reference.yml b/filebeat/filebeat.reference.yml index ca23e95aea9..a654e5b9944 100644 --- a/filebeat/filebeat.reference.yml +++ b/filebeat/filebeat.reference.yml @@ -1167,8 +1167,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template ===================================== diff --git a/heartbeat/heartbeat.reference.yml b/heartbeat/heartbeat.reference.yml index 328a056551e..015f854fa66 100644 --- a/heartbeat/heartbeat.reference.yml +++ b/heartbeat/heartbeat.reference.yml @@ -842,8 +842,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template ===================================== diff --git a/libbeat/_meta/config.reference.yml b/libbeat/_meta/config.reference.yml index a79c333b141..4c19ee41260 100644 --- a/libbeat/_meta/config.reference.yml +++ b/libbeat/_meta/config.reference.yml @@ -628,8 +628,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template ===================================== diff --git a/libbeat/cmd/instance/beat.go b/libbeat/cmd/instance/beat.go index 89fe1d78050..4f6493c9734 100644 --- a/libbeat/cmd/instance/beat.go +++ b/libbeat/cmd/instance/beat.go @@ -537,13 +537,13 @@ func (b *Beat) loadDashboards(force bool) error { } } - if b.Config.Dashboards != nil && b.Config.Dashboards.Enabled() { + if b.Config.Dashboards.Enabled() { var esConfig *common.Config if b.Config.Output.Name() == "elasticsearch" { esConfig = b.Config.Output.Config() } - err := dashboards.ImportDashboards(b.Info.Beat, b.Info.Name, paths.Resolve(paths.Home, ""), + err := dashboards.ImportDashboards(b.Info.Beat, b.Info.Hostname, paths.Resolve(paths.Home, ""), b.Config.Kibana, esConfig, b.Config.Dashboards, nil) if err != nil { return fmt.Errorf("Error importing Kibana dashboards: %v", err) diff --git a/libbeat/dashboards/dashboards.go b/libbeat/dashboards/dashboards.go index ab34d85f527..18ebffd1e82 100644 --- a/libbeat/dashboards/dashboards.go +++ b/libbeat/dashboards/dashboards.go @@ -1,72 +1,115 @@ package dashboards import ( + "errors" "fmt" "path/filepath" "strconv" "strings" "github.com/elastic/beats/libbeat/common" - "github.com/elastic/beats/libbeat/logp" ) -func ImportDashboards(beatName, hostname, homePath string, - kibanaConfig *common.Config, esConfig *common.Config, - dashboardsConfig *common.Config, msgOutputter MessageOutputter) error { +type importMethod uint8 +// check import route +const ( + importNone importMethod = iota + importViaKibana + importViaES +) + +// ImportDashboards tries to import the kibana dashboards. +// If the Elastic Stack is at version 6.0+, the dashboards should be installed +// via the kibana dashboard loader plugin. For older versions of the Elastic Stack +// we write the dashboards directly into the .kibana index. +func ImportDashboards( + beatName, hostname, homePath string, + kibanaConfig, esConfig, dashboardsConfig *common.Config, + msgOutputter MessageOutputter, +) error { if dashboardsConfig == nil || !dashboardsConfig.Enabled() { return nil } + // unpack dashboard config dashConfig := defaultConfig dashConfig.Beat = beatName - if dashConfig.Dir == "" { - dashConfig.Dir = filepath.Join(homePath, defaultDirectory) - } - + dashConfig.Dir = filepath.Join(homePath, defaultDirectory) err := dashboardsConfig.Unpack(&dashConfig) if err != nil { return err } + // init kibana config object if kibanaConfig == nil { kibanaConfig = common.NewConfig() } - if esConfig == nil && dashConfig.AlwaysKibana { - return setupAndImportDashboardsViaKibana(hostname, kibanaConfig, &dashConfig, msgOutputter) - } - - esLoader, err := NewElasticsearchLoader(esConfig, &dashConfig, msgOutputter) - if err != nil { - return fmt.Errorf("fail to create the Elasticsearch loader: %v", err) - } - defer esLoader.Close() - - esLoader.statusMsg("Elasticsearch URL %v", esLoader.client.Connection.URL) - - majorVersion, _, err := getMajorAndMinorVersion(esLoader.version) - if err != nil { - return fmt.Errorf("wrong Elasticsearch version: %v", err) - } - - if majorVersion < 6 { + if !kibanaConfig.HasField("host") { + // fallback to the beats hostname (localhost) if host is not configured + kibanaConfig.SetString("host", -1, hostname) + } + if esConfig.Enabled() { + username, _ := esConfig.String("username", -1) + password, _ := esConfig.String("password", -1) + + if !kibanaConfig.HasField("username") && username != "" { + kibanaConfig.SetString("username", -1, username) + } + if !kibanaConfig.HasField("password") && password != "" { + kibanaConfig.SetString("password", -1, password) + } + } + + var esLoader *ElasticsearchLoader + + importVia := importNone + useKibana := importViaKibana + if !kibanaConfig.Enabled() { + useKibana = importNone + } + + requiresKibana := dashConfig.AlwaysKibana || !esConfig.Enabled() + if requiresKibana { + importVia = useKibana + } else { + // Check import route via elasticsearch version. If Elasticsearch major + // version is >6, we assume Kibana also being at versions >6.0. In this + // case dashboards will be imported using the new kibana dashboard loader + // plugin. + // XXX(urso): Why do we test the Elasticsearch version? If kibana is + // configured, why not test the kibana version and plugin + // availability first? + esLoader, err = NewElasticsearchLoader(esConfig, &dashConfig, msgOutputter) + if err != nil { + return fmt.Errorf("fail to create the Elasticsearch loader: %v", err) + } + defer esLoader.Close() + + esLoader.statusMsg("Elasticsearch URL %v", esLoader.client.Connection.URL) + + majorVersion, _, err := getMajorAndMinorVersion(esLoader.version) + if err != nil { + return fmt.Errorf("wrong Elasticsearch version: %v", err) + } + + if majorVersion < 6 { + importVia = importViaES + } else { + importVia = useKibana + } + } + + // Try to import dashboards. + switch importVia { + case importViaES: return ImportDashboardsViaElasticsearch(esLoader) + case importViaKibana: + return setupAndImportDashboardsViaKibana(hostname, kibanaConfig, &dashConfig, msgOutputter) + default: + return errors.New("Elasticsearch or Kibana configuration missing for loading dashboards.") } - - logp.Info("For Elasticsearch version >= 6.0.0, the Kibana dashboards need to be imported via the Kibana API.") - - // In Cloud, the Kibana URL is different than the Elasticsearch URL, - // but the credentials are the same. - // So, by default, use same credentials for connecting to Kibana as to Elasticsearch - if !kibanaConfig.HasField("username") && len(esLoader.client.Username) > 0 { - kibanaConfig.SetString("username", -1, esLoader.client.Username) - } - if !kibanaConfig.HasField("password") && len(esLoader.client.Password) > 0 { - kibanaConfig.SetString("password", -1, esLoader.client.Password) - } - - return setupAndImportDashboardsViaKibana(hostname, kibanaConfig, &dashConfig, msgOutputter) } func setupAndImportDashboardsViaKibana(hostname string, kibanaConfig *common.Config, diff --git a/metricbeat/metricbeat.reference.yml b/metricbeat/metricbeat.reference.yml index 89d4a909e53..0dcae707814 100644 --- a/metricbeat/metricbeat.reference.yml +++ b/metricbeat/metricbeat.reference.yml @@ -1109,8 +1109,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template ===================================== diff --git a/packetbeat/packetbeat.reference.yml b/packetbeat/packetbeat.reference.yml index 63e0a94b0b6..e14c48583ea 100644 --- a/packetbeat/packetbeat.reference.yml +++ b/packetbeat/packetbeat.reference.yml @@ -1096,8 +1096,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template ===================================== diff --git a/winlogbeat/winlogbeat.reference.yml b/winlogbeat/winlogbeat.reference.yml index 53ea4686894..7cf1fc3eb4c 100644 --- a/winlogbeat/winlogbeat.reference.yml +++ b/winlogbeat/winlogbeat.reference.yml @@ -657,8 +657,9 @@ output.elasticsearch: # dashboards and index pattern. Example: testbeat-* #setup.dashboards.index: -# Force loading of dashboards using the Kibana API without querying Elasticsearch for the version -#always_kibana: false +# Always use the Kibana API for loading the dashboards instead of autodetecting +# how to install the dashboards by first querying Elasticsearch. +#setup.dashboards.always_kibana: false #============================== Template =====================================