1717package org .apache .cloudstack .metrics ;
1818
1919import com .cloud .utils .component .ManagerBase ;
20+ import com .cloud .utils .net .NetUtils ;
2021import com .sun .net .httpserver .HttpExchange ;
2122import com .sun .net .httpserver .HttpHandler ;
2223import com .sun .net .httpserver .HttpServer ;
3132import java .net .UnknownHostException ;
3233import java .nio .charset .StandardCharsets ;
3334import java .util .Arrays ;
34- import java .util .List ;
35+ import java .util .Collections ;
36+ import java .util .Objects ;
37+ import java .util .Set ;
3538import java .util .stream .Collectors ;
3639
3740public class PrometheusExporterServerImpl extends ManagerBase implements PrometheusExporterServer , Configurable {
@@ -41,6 +44,9 @@ public class PrometheusExporterServerImpl extends ManagerBase implements Prometh
4144 @ Inject
4245 private PrometheusExporter prometheusExporter ;
4346
47+ private String allowedAddressesConfig ;
48+ private Set <String > allowedAddresses = Collections .emptySet ();
49+
4450 private final class ExporterHandler implements HttpHandler {
4551 private PrometheusExporter prometheusExporter ;
4652
@@ -55,17 +61,7 @@ public void handle(final HttpExchange httpExchange) throws IOException {
5561 logger .debug ("Prometheus exporter received client request from: " + remoteClientAddress );
5662 String response = "Forbidden" ;
5763 int responseCode = 403 ;
58- final List <String > allowedAddresses = Arrays .stream (PrometheusExporterAllowedAddresses .value ().split ("," ))
59- .map (addr -> {
60- try {
61- return InetAddress .getByName (addr .trim ()).getHostAddress ();
62- } catch (UnknownHostException e ) {
63- logger .warn ("Invalid IP address in prometheus.exporter.allowed.ips: " + addr .trim ());
64- return addr .trim ();
65- }
66- })
67- .collect (Collectors .toList ());
68- if (allowedAddresses .contains (remoteClientAddress )) {
64+ if (getAllowedAddresses ().contains (remoteClientAddress )) {
6965 prometheusExporter .updateMetrics ();
7066 response = prometheusExporter .getMetrics ();
7167 responseCode = 200 ;
@@ -88,6 +84,42 @@ public void handle(final HttpExchange httpExchange) throws IOException {
8884 }
8985 }
9086
87+ private synchronized Set <String > getAllowedAddresses () {
88+ final String config = PrometheusExporterAllowedAddresses .value ();
89+ if (!config .equals (allowedAddressesConfig )) {
90+ allowedAddresses = normalizeAddresses (config );
91+ allowedAddressesConfig = config ;
92+ }
93+ return allowedAddresses ;
94+ }
95+
96+ /**
97+ * Normalizes a comma separated list of IP addresses to their canonical text form, so that
98+ * equivalent notations (e.g. ::1 and 0:0:0:0:0:0:0:1) match the remote client address.
99+ * Blank entries and anything that is not an IP literal are ignored, so no DNS resolution takes place.
100+ */
101+ protected Set <String > normalizeAddresses (final String addresses ) {
102+ return Arrays .stream (addresses .split ("," ))
103+ .map (String ::trim )
104+ .filter (addr -> !addr .isEmpty ())
105+ .map (this ::normalizeAddress )
106+ .filter (Objects ::nonNull )
107+ .collect (Collectors .toSet ());
108+ }
109+
110+ private String normalizeAddress (final String address ) {
111+ if (!NetUtils .isValidIp4 (address ) && !NetUtils .isValidIp6 (address )) {
112+ logger .warn ("Ignoring invalid IP address [{}] in {}" , address , PrometheusExporterAllowedAddresses .key ());
113+ return null ;
114+ }
115+ try {
116+ return InetAddress .getByName (address ).getHostAddress ();
117+ } catch (UnknownHostException e ) {
118+ logger .warn ("Ignoring IP address [{}] in {} that could not be parsed" , address , PrometheusExporterAllowedAddresses .key (), e );
119+ return null ;
120+ }
121+ }
122+
91123 @ Override
92124 public boolean start () {
93125 if (EnablePrometheusExporter .value ()) {
0 commit comments