Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

(DIO-563) addresses CVE-2020-7943 #92

Merged
merged 1 commit into from
Apr 7, 2020
Merged

(DIO-563) addresses CVE-2020-7943 #92

merged 1 commit into from
Apr 7, 2020

Conversation

suckatrash
Copy link
Contributor

@suckatrash suckatrash commented Mar 20, 2020

This PR addresses the changes to metrics endpoints required by CVE-2020-7943:

  • Returns ['localhost'] in localhost_or_hosts_with_pe_profile() if puppet_version is greater than 6.14.0 9 or greater than 5.5.19 but below v6) when the function runs on the master. If not run on the master, an empty array is returned.
  • Changes the default of puppetdb_host in puppet_metrics_dashboard::profile::puppetdb to localhost. This would be overridden when called from puppet_metrics_dashboard::telegraf::config when a list of puppetdb hosts is returned from localhost_or_hosts_with_pe_profile()
  • Changes metrics URLs as appropriate
  • Updates dashboards with new metric value and uses the host tag instead of server (so we don't see localhost on all the dashes).
  • Adds test coverage for running on / not running on master
  • Adds a tidy resource to cleanup unmanaged dashboards

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

The changes themselves look good!
Any change you could replace doc refs to Puppetdb with PuppetDB?
Sorry, I can't help with Travis ...

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

@suckatrash I assume we should wait for this to be merged before merging the release PR and publishing 2.2.0 and releasing the coupled puppet_metrics_collector 6.0.0?

@suckatrash
Copy link
Contributor Author

@tkishel I don't want to hold anything up with this. I may not finish it today so I'd say go ahead with a release

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

Well, we made the same endpoint change in puppet_metrics_collector 6.0.0.
I've restarted the tests as they don't seem to be failing because of this.

@suckatrash
Copy link
Contributor Author

I think we might need to reconsider using pe_server_version since that won't work with opensource puppet.

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

I think we might need to reconsider using pe_server_version since that won't work with opensource puppet.

Well, it cleared all the Travis errors :)

I use the Puppet version to detect PE version here:

https://github.com/tkishel/pe_tune/blob/master/lib/puppet_x/puppetlabs/tune.rb#L1050

So how about this:

  # Puppet 6.14 correlates to PE 2019.5
  if (versioncmp($facts['puppetversion'], '6.14.0') >= 1) and ($profile == 'puppetdb') {

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

Yay!

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

Note that it's possible that the agent's Puppet version differs from the Master (or that of the PuppetDB host). We could check $server_facts['serverversion'] but that will not be populated if/when declaring a class via puppet apply

@tkishel
Copy link
Contributor

tkishel commented Mar 20, 2020

For PE 2018.1.13 ...


if ($profile == 'puppetdb') {
  # PE 2019.5 or newer with Puppet Server 6.9.2 or newer, or
  # PE 2018.1.13 or newer PE 2018 with Puppet Server 5.3.12 or newer
  # As per: https://puppet.com/docs/pe/latest/component_versions_in_recent_pe_releases.html
  if ((versioncmp($facts['puppetversion'], '6.14.0') >= 1) or
      (versioncmp($facts['puppetversion'], '5.5.19') >= 1) and (versioncmp($facts['puppetversion'], '6.0.0') == -1)) {
    notice ( 'In puppetserver version 6.9.2 or 5.3.12 and newer you must apply the puppet_metrics_dashboard::profile::puppetdb class to any puppetdb hosts. Metrics cannot be collected by telegraf from a remote agent.')
    $hosts = []
  } else {

  }     
}

@tkishel
Copy link
Contributor

tkishel commented Apr 1, 2020

Travis is failing because there is no else block to the if ($profile == 'puppetdb') { statement.

We can easily resolve that, I don't think we should emit a notice as even if the user applies the puppet_metrics_dashboard::profile::puppetdb class to PuppetDB hosts, the notice will continue to be emitted during every run.

# @summary function used to determine hosts with a Puppet Enterprise profile
#
# Queries PuppetDB for hosts with the specified Puppet Enterprise profile.
# Used by this module to identify hosts with Puppet Enterprise API endpoints.
#
# @param profile [String]
#   The short name of the Puppet Enterprise profile to query.
#
# @return [Array[String]]
#   An array of certnames from the query, or the certname of the localhost when the query returns no hosts.

function puppet_metrics_dashboard::localhost_or_hosts_with_pe_profile(
  String $profile,
) >> Array {
  # storeconfigs is: https://puppet.com/docs/puppet/latest/configuration.html#storeconfigs
  if $settings::storeconfigs {
    $_profile = capitalize($profile)
    $hosts = puppetdb_query("resources[certname] {
      type = 'Class' and
      title = 'Puppet_enterprise::Profile::${_profile}' and
      nodes { deactivated is null and expired is null }
    }").map |$nodes| { $nodes['certname'] }

  } else {
    $hosts = []
  }

  if empty($hosts) {
    [$trusted['certname']]
  } else {
    # PuppetDB in PE 2019.5 or newer (or PE 2018.1.13 or newer PE 2018) do not allow remote access to metrics, as a result of CVE-2020-7943.
    # Mapping of Puppet to PE to PuppetDB versions is: https://puppet.com/docs/pe/latest/component_versions_in_recent_pe_releases.html
    $puppetdb_no_remote_metrics = ((versioncmp($facts['puppetversion'], '6.14.0') >= 0) or (versioncmp($facts['puppetversion'], '5.5.19') >= 0) and (versioncmp($facts['puppetversion'], '6.0.0') == -1))
    if ($profile == 'puppetdb') and $puppetdb_no_remote_metrics) {
      # Enabling this would result in a notice during every run, even if you apply the class.
      # notice ('With this version of PuppetDB, you must apply the puppet_metrics_dashboard::profile::puppetdb class to PuppetDB hosts: metrics cannot be remotely collected by Telegraf.')
      $hosts.filter |$host| { $host == $trusted['certname'] }  
    } else {
      sort($hosts)  
    }
  }
}

@suckatrash
Copy link
Contributor Author

Right, I forgot about that use-case. Then we need to return ['localhost'] in that case since I think since the service only listens there in the versions we're accommodating.

@tkishel
Copy link
Contributor

tkishel commented Apr 1, 2020

True. Maybe ...

$localhosts = $hosts.filter |$host| { $host == $trusted['certname'] }
$localhosts.map |$host| { '127.0.0.1' }

@suckatrash suckatrash force-pushed the cve_2020_7943 branch 15 times, most recently from 7726591 to 274f580 Compare April 3, 2020 07:04
@suckatrash suckatrash force-pushed the cve_2020_7943 branch 4 times, most recently from 2257a32 to dad604a Compare April 3, 2020 07:31
if $facts['puppet_server'] == $trusted['certname'] {
$hosts = ['localhost']
} else {
$hosts = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this, I know its an "unnecessary" assignment for a return value, but it makes it easier to read!

@suckatrash suckatrash force-pushed the cve_2020_7943 branch 10 times, most recently from 7e2d040 to fe83ee6 Compare April 6, 2020 15:40
@suckatrash suckatrash marked this pull request as ready for review April 6, 2020 16:00
@suckatrash suckatrash requested a review from tkishel April 6, 2020 17:15
@suckatrash suckatrash requested a review from genebean April 6, 2020 17:53
@suckatrash
Copy link
Contributor Author

I'll squash these commits once all looks good here

Copy link
Contributor

@tkishel tkishel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a lot of good work!

Copy link
Contributor

@genebean genebean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks fine to me. One thing that stood out is it seems this chunk is used all over the place:

if ((versioncmp($facts['puppetversion'], '6.14.0') >= 0) or 
         (versioncmp($facts['puppetversion'], '5.5.19') >= 0) and (versioncmp($facts['puppetversion'], '6.0.0') < 1))

Maybe that should be pulled out into a function to simplify things.

@genebean
Copy link
Contributor

genebean commented Apr 7, 2020

Nice work everyone

@suckatrash suckatrash deleted the cve_2020_7943 branch April 7, 2020 23:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants