Skip to content

Commit d8b111a

Browse files
committed
(PE-28451) switch from the v1 to v2 metrics api
With this commit ... We switch from the v1 to v2 Metrics API for additional metrics (for PuppetDB), and drop metrics for unsupported versions of PE. (This is required in response to PE-28451 / PE-28468. Note these additional metrics generate errors in PE 2019.4 via v2: puppetlabs.puppetdb.ha:name=failed-request-counter puppetlabs.puppetdb.mq:name=global.generate-retry-message-time puppetlabs.puppetdb.mq:name=global.retry-persistence-time
1 parent 98e4a76 commit d8b111a

File tree

7 files changed

+337
-250
lines changed

7 files changed

+337
-250
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Table of Contents
2121
This module collects metrics provided by the status endpoints of Puppet Enterprise services.
2222
The metrics can be used to identify performance issues that may be addressed by performance tuning.
2323

24+
> In PE 2018.1.13 and newer and PE 2019.4 and newer, the `/metrics/v1` endpoints are disabled by default and access to the `/metrics/v2` endpoints are restricted to localhost ... in response to CVE-2020-7943.
25+
This module requires access those endpoints to collect additional metrics from PuppetDB, and those metrics will not be collected from remote PuppetDB hosts until these restricted are resolved.
26+
Refer to [Configuration for Distributed Metrics Collection](#Configuration-for-distributed-metrics-collection) for a workaround.
27+
2428

2529
## Setup
2630

files/pe_metrics.rb

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,20 @@ def setup_connection(url, use_ssl)
8383
def get_endpoint(url, use_ssl)
8484
http, uri = setup_connection(url, use_ssl)
8585

86-
data = JSON.parse(http.get(uri.request_uri).body)
86+
endpoint_data = JSON.parse(http.get(uri.request_uri).body)
87+
if endpoint_data.key?('status')
88+
if endpoint_data['status'] == 200
89+
endpoint_data = endpoint_data['value']
90+
else
91+
$error_array << "HTTP Error #{endpoint_data['status']} for #{url}"
92+
endpoint_data = {}
93+
end
94+
end
95+
return endpoint_data
96+
8797
rescue Exception => e
88-
$error_array << "#{e}"
89-
data = {}
98+
$error_array << "#{e}"
99+
endpoint_data = {}
90100
end
91101

92102
def post_endpoint(url, use_ssl, post_data)
@@ -96,50 +106,37 @@ def post_endpoint(url, use_ssl, post_data)
96106
request.content_type = 'application/json'
97107
request.body = post_data
98108

99-
data = JSON.parse(http.request(request).body)
109+
endpoint_data = JSON.parse(http.request(request).body)
110+
return endpoint_data
111+
100112
rescue Exception => e
101-
$error_array << "#{e}"
102-
data = {}
113+
$error_array << "#{e}"
114+
endpoint_data = {}
103115
end
104116

105-
def individually_retrieve_additional_metrics(host, port, use_ssl, metrics)
106-
host_url = generate_host_url(host, port, use_ssl)
117+
# PE-28451 Disables Metrics API v1 (/metrics/v1/beans/) and restricts v2 (/metrics/v2/read/) to localhost by default.
107118

108-
metrics_array = []
109-
metrics.each do |metric|
110-
endpoint = URI.escape("#{host_url}/metrics/v1/mbeans/#{metric['url']}")
111-
metrics_array << { 'name' => metric['name'], 'data' => get_endpoint(endpoint, use_ssl) }
119+
def retrieve_additional_metrics(host, port, use_ssl, metrics_type, metrics)
120+
if metrics_type == 'puppetdb'
121+
host = '127.0.0.1' if host == CERTNAME
122+
return [] unless ['127.0.0.1', 'localhost'].include?(host)
112123
end
113124

114-
return metrics_array
115-
end
116-
117-
def bulk_retrieve_additional_metrics(host, port, use_ssl, metrics)
118125
host_url = generate_host_url(host, port, use_ssl)
119126

120-
post_data = []
121-
metrics.each do |metric|
122-
post_data << metric['url']
123-
end
127+
endpoint = "#{host_url}/metrics/v2/read"
128+
metrics_output = post_endpoint(endpoint, use_ssl, metrics.to_json)
124129

125-
endpoint = "#{host_url}/metrics/v1/mbeans"
126-
metrics_output = post_endpoint(endpoint, use_ssl, post_data.to_json)
127130
metrics_array = []
128-
129131
metrics.each_index do |index|
130132
metric_name = metrics[index]['name']
131133
metric_data = metrics_output[index]
132-
metrics_array << { 'name' => metric_name, 'data' => metric_data }
133-
end
134-
135-
return metrics_array
136-
end
137-
138-
def retrieve_additional_metrics(host, port, use_ssl, pe_version, metrics)
139-
if Gem::Version.new(pe_version) < Gem::Version.new('2016.2.0') then
140-
metrics_array = individually_retrieve_additional_metrics(host, port, use_ssl, metrics)
141-
else
142-
metrics_array = bulk_retrieve_additional_metrics(host, port, use_ssl, metrics)
134+
if metric_data['status'] == 200
135+
metrics_array << { 'name' => metric_name, 'data' => metric_data['value'] }
136+
else
137+
metric_mbean = metrics[index]['mbean']
138+
$error_array << "HTTP Error #{metric_data['status']} for #{metric_mbean}"
139+
end
143140
end
144141

145142
return metrics_array

files/tk_metrics

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ HOSTS.each do |host|
2626
dataset['servers'][hostkey][METRICS_TYPE] = status_output
2727

2828
unless ADDITIONAL_METRICS.empty? then
29-
metrics_array = retrieve_additional_metrics(host, PORT, USE_SSL, PE_VERSION, ADDITIONAL_METRICS)
29+
metrics_array = retrieve_additional_metrics(host, PORT, USE_SSL, METRICS_TYPE, ADDITIONAL_METRICS)
3030
metrics_array.each do |metric_hash|
3131
metric_name = metric_hash['name']
3232
metric_data = metric_hash['data']

manifests/service/activemq.pp

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,44 +12,6 @@
1212
Optional[Integer] $metrics_server_port = $puppet_metrics_collector::metrics_server_port,
1313
Optional[String] $metrics_server_db_name = $puppet_metrics_collector::metrics_server_db_name,
1414
) {
15-
$additional_metrics = [
16-
{
17-
'type' => 'read',
18-
'mbean' => 'java.lang:type=Memory',
19-
'attribute' => 'HeapMemoryUsage,NonHeapMemoryUsage'
20-
},
21-
{
22-
'type' => 'read',
23-
'mbean' => 'java.lang:name=*,type=GarbageCollector',
24-
'attribute' => 'CollectionCount'
25-
},
26-
{
27-
'type' => 'read',
28-
'mbean' => 'java.lang:type=Runtime',
29-
'attribute' => 'Uptime'
30-
},
31-
{
32-
'type' => 'read',
33-
'mbean' => 'java.lang:type=OperatingSystem',
34-
'attribute' => 'OpenFileDescriptorCount,MaxFileDescriptorCount'
35-
},
36-
{
37-
'type' => 'read',
38-
'mbean' => 'org.apache.activemq:brokerName=*,type=Broker',
39-
'attribute' => 'MemoryLimit,MemoryPercentUsage,CurrentConnectionsCount'
40-
},
41-
{
42-
'type' => 'read',
43-
'mbean' => 'org.apache.activemq:type=Broker,brokerName=*,destinationType=Queue,destinationName=mcollective.*',
44-
'attribute' => 'AverageBlockedTime,AverageEnqueueTime,AverageMessageSize,ConsumerCount,DequeueCount,DispatchCount,EnqueueCount,ExpiredCount,ForwardCount,InFlightCount,ProducerCount,QueueSize',
45-
},
46-
{
47-
'type' => 'read',
48-
'mbean' => 'org.apache.activemq:type=Broker,brokerName=*,destinationType=Topic,destinationName=mcollective.*.agent',
49-
'attribute' => 'AverageBlockedTime,AverageEnqueueTime,AverageMessageSize,ConsumerCount,DequeueCount,DispatchCount,EnqueueCount,ExpiredCount,ForwardCount,InFlightCount,ProducerCount,QueueSize',
50-
},
51-
]
52-
5315
file { "${puppet_metrics_collector::scripts_dir}/amq_metrics" :
5416
ensure => $metrics_ensure,
5517
mode => '0755',
@@ -65,7 +27,7 @@
6527
metric_script_file => 'amq_metrics',
6628
override_metrics_command => $override_metrics_command,
6729
excludes => $excludes,
68-
additional_metrics => $additional_metrics,
30+
additional_metrics => [],
6931
metrics_server_type => $metrics_server_type,
7032
metrics_server_hostname => $metrics_server_hostname,
7133
metrics_server_port => $metrics_server_port,

0 commit comments

Comments
 (0)