Merge branch 'master' into network_route

This commit is contained in:
Ben Kochie 2021-01-24 14:46:00 +01:00 committed by GitHub
commit 8536df5bbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 906 additions and 1578 deletions

View File

@ -8,7 +8,7 @@ repository:
build: build:
binaries: binaries:
- name: node_exporter - name: node_exporter
flags: -a -tags 'netgo static_build' flags: -a -tags 'netgo osusergo static_build'
ldflags: | ldflags: |
-X github.com/prometheus/common/version.Version={{.Version}} -X github.com/prometheus/common/version.Version={{.Version}}
-X github.com/prometheus/common/version.Revision={{.Revision}} -X github.com/prometheus/common/version.Revision={{.Revision}}

View File

@ -7,7 +7,7 @@ repository:
build: build:
binaries: binaries:
- name: node_exporter - name: node_exporter
flags: -a -tags 'netgo static_build' flags: -a -tags 'netgo osusergo static_build'
ldflags: | ldflags: |
-X github.com/prometheus/common/version.Version={{.Version}} -X github.com/prometheus/common/version.Version={{.Version}}
-X github.com/prometheus/common/version.Revision={{.Revision}} -X github.com/prometheus/common/version.Revision={{.Revision}}
@ -31,3 +31,4 @@ crossbuild:
- linux/ppc64 - linux/ppc64
- linux/ppc64le - linux/ppc64le
- linux/s390x - linux/s390x
- openbsd/amd64

View File

@ -5,6 +5,8 @@
* [FEATURE] * [FEATURE]
* [ENHANCEMENT] Include TCP OutRsts in netstat metrics * [ENHANCEMENT] Include TCP OutRsts in netstat metrics
* [ENHANCEMENT] Added XFS inode operations to XFS metrics * [ENHANCEMENT] Added XFS inode operations to XFS metrics
* [ENHANCEMENT] Remove CGO dependencies for OpenBSD amd64
* [BUGFIX] Handle EPERM for syscall in timex collector
* [BUGFIX] * [BUGFIX]
## 1.0.1 / 2020-06-15 ## 1.0.1 / 2020-06-15

View File

@ -44,9 +44,18 @@ else
else else
PROMU_CONF ?= .promu-cgo.yml PROMU_CONF ?= .promu-cgo.yml
endif endif
else
# Do not use CGO for openbsd/amd64 builds
ifeq ($(GOOS), openbsd)
ifeq ($(GOARCH), amd64)
PROMU_CONF ?= .promu.yml
else else
PROMU_CONF ?= .promu-cgo.yml PROMU_CONF ?= .promu-cgo.yml
endif endif
else
PROMU_CONF ?= .promu-cgo.yml
endif
endif
endif endif
PROMU := $(FIRST_GOPATH)/bin/promu --config $(PROMU_CONF) PROMU := $(FIRST_GOPATH)/bin/promu --config $(PROMU_CONF)

View File

@ -14,6 +14,64 @@ To expose NVIDIA GPU metrics, [prometheus-dcgm
](https://github.com/NVIDIA/gpu-monitoring-tools#dcgm-exporter) ](https://github.com/NVIDIA/gpu-monitoring-tools#dcgm-exporter)
can be used. can be used.
## Installation and Usage
If you are new to Prometheus and `node_exporter` there is a [simple step-by-step guide](https://prometheus.io/docs/guides/node-exporter/).
### Ansible
For automated installs with [Ansible](https://www.ansible.com/), there is the [Cloud Alchemy role](https://github.com/cloudalchemy/ansible-node-exporter).
### RHEL/CentOS/Fedora
There is a [community-supplied COPR repository](https://copr.fedorainfracloud.org/coprs/ibotty/prometheus-exporters/) which closely follows upstream releases.
### Docker
The `node_exporter` is designed to monitor the host system. It's not recommended
to deploy it as a Docker container because it requires access to the host system.
For situations where Docker deployment is needed, some extra flags must be used to allow
the `node_exporter` access to the host namespaces.
Be aware that any non-root mount points you want to monitor will need to be bind-mounted
into the container.
If you start container for host monitoring, specify `path.rootfs` argument.
This argument must match path in bind-mount of host root. The node\_exporter will use
`path.rootfs` as prefix to access host filesystem.
```bash
docker run -d \
--net="host" \
--pid="host" \
-v "/:/host:ro,rslave" \
quay.io/prometheus/node-exporter:latest \
--path.rootfs=/host
```
For Docker compose, similar flag changes are needed.
```yaml
---
version: '3.8'
services:
node_exporter:
image: quay.io/prometheus/node-exporter:latest
container_name: node_exporter
command:
- '--path.rootfs=/host'
network_mode: host
pid: host
restart: unless-stopped
volumes:
- '/:/host:ro,rslave'
```
On some systems, the `timex` collector requires an additional Docker flag,
`--cap-add=SYS_TIME`, in order to access the required syscalls.
## Collectors ## Collectors
There is varying support for collectors on each operating system. The tables There is varying support for collectors on each operating system. The tables
@ -29,9 +87,10 @@ Name | Description | OS
arp | Exposes ARP statistics from `/proc/net/arp`. | Linux arp | Exposes ARP statistics from `/proc/net/arp`. | Linux
bcache | Exposes bcache statistics from `/sys/fs/bcache/`. | Linux bcache | Exposes bcache statistics from `/sys/fs/bcache/`. | Linux
bonding | Exposes the number of configured and active slaves of Linux bonding interfaces. | Linux bonding | Exposes the number of configured and active slaves of Linux bonding interfaces. | Linux
btrfs | Exposes btrfs statistics | Linux
boottime | Exposes system boot time derived from the `kern.boottime` sysctl. | Darwin, Dragonfly, FreeBSD, NetBSD, OpenBSD, Solaris boottime | Exposes system boot time derived from the `kern.boottime` sysctl. | Darwin, Dragonfly, FreeBSD, NetBSD, OpenBSD, Solaris
conntrack | Shows conntrack statistics (does nothing if no `/proc/sys/net/netfilter/` present). | Linux conntrack | Shows conntrack statistics (does nothing if no `/proc/sys/net/netfilter/` present). | Linux
cpu | Exposes CPU statistics | Darwin, Dragonfly, FreeBSD, Linux, Solaris cpu | Exposes CPU statistics | Darwin, Dragonfly, FreeBSD, Linux, Solaris, OpenBSD
cpufreq | Exposes CPU frequency statistics | Linux, Solaris cpufreq | Exposes CPU frequency statistics | Linux, Solaris
diskstats | Exposes disk I/O statistics. | Darwin, Linux, OpenBSD diskstats | Exposes disk I/O statistics. | Darwin, Linux, OpenBSD
edac | Exposes error detection and correction statistics. | Linux edac | Exposes error detection and correction statistics. | Linux
@ -50,6 +109,7 @@ netdev | Exposes network interface statistics such as bytes transferred. | Darwi
netstat | Exposes network statistics from `/proc/net/netstat`. This is the same information as `netstat -s`. | Linux netstat | Exposes network statistics from `/proc/net/netstat`. This is the same information as `netstat -s`. | Linux
nfs | Exposes NFS client statistics from `/proc/net/rpc/nfs`. This is the same information as `nfsstat -c`. | Linux nfs | Exposes NFS client statistics from `/proc/net/rpc/nfs`. This is the same information as `nfsstat -c`. | Linux
nfsd | Exposes NFS kernel server statistics from `/proc/net/rpc/nfsd`. This is the same information as `nfsstat -s`. | Linux nfsd | Exposes NFS kernel server statistics from `/proc/net/rpc/nfsd`. This is the same information as `nfsstat -s`. | Linux
powersupplyclass | Exposes Power Supply statistics from `/sys/class/power_supply` | Linux
pressure | Exposes pressure stall statistics from `/proc/pressure/`. | Linux (kernel 4.20+ and/or [CONFIG\_PSI](https://www.kernel.org/doc/html/latest/accounting/psi.html)) pressure | Exposes pressure stall statistics from `/proc/pressure/`. | Linux (kernel 4.20+ and/or [CONFIG\_PSI](https://www.kernel.org/doc/html/latest/accounting/psi.html))
rapl | Exposes various statistics from `/sys/class/powercap`. | Linux rapl | Exposes various statistics from `/sys/class/powercap`. | Linux
schedstat | Exposes task scheduler statistics from `/proc/schedstat`. | Linux schedstat | Exposes task scheduler statistics from `/proc/schedstat`. | Linux
@ -181,7 +241,7 @@ For advanced use the `node_exporter` can be passed an optional list of collector
This can be useful for having different Prometheus servers collect specific metrics from nodes. This can be useful for having different Prometheus servers collect specific metrics from nodes.
## Building and running ## Development building and running
Prerequisites: Prerequisites:
@ -190,8 +250,8 @@ Prerequisites:
Building: Building:
go get github.com/prometheus/node_exporter git clone https://github.com/prometheus/node_exporter.git
cd ${GOPATH-$HOME/go}/src/github.com/prometheus/node_exporter cd node_exporter
make make
./node_exporter <flags> ./node_exporter <flags>
@ -213,33 +273,7 @@ The exporter supports TLS via a new web configuration file.
./node_exporter --web.config=web-config.yml ./node_exporter --web.config=web-config.yml
``` ```
See the [https package](https/README.md) for more details. See the [exporter-toolkit https package](https://github.com/prometheus/exporter-toolkit/blob/v0.1.0/https/README.md) for more details.
## Using Docker
The `node_exporter` is designed to monitor the host system. It's not recommended
to deploy it as a Docker container because it requires access to the host system.
Be aware that any non-root mount points you want to monitor will need to be bind-mounted
into the container.
If you start container for host monitoring, specify `path.rootfs` argument.
This argument must match path in bind-mount of host root. The node\_exporter will use
`path.rootfs` as prefix to access host filesystem.
```bash
docker run -d \
--net="host" \
--pid="host" \
-v "/:/host:ro,rslave" \
quay.io/prometheus/node-exporter \
--path.rootfs=/host
```
On some systems, the `timex` collector requires an additional Docker flag,
`--cap-add=SYS_TIME`, in order to access the required syscalls.
## Using a third-party repository for RHEL/CentOS/Fedora
There is a [community-supplied COPR repository](https://copr.fedorainfracloud.org/coprs/ibotty/prometheus-exporters/) which closely follows upstream releases.
[travis]: https://travis-ci.org/prometheus/node_exporter [travis]: https://travis-ci.org/prometheus/node_exporter
[hub]: https://hub.docker.com/r/prom/node-exporter/ [hub]: https://hub.docker.com/r/prom/node-exporter/

View File

@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build freebsd dragonfly openbsd netbsd darwin // +build freebsd dragonfly openbsd,!amd64 netbsd darwin
// +build !noboottime // +build !noboottime
package collector package collector

View File

@ -0,0 +1,61 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !noboottime
package collector
import (
"github.com/go-kit/kit/log"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/unix"
"unsafe"
)
type bootTimeCollector struct {
name, description string
logger log.Logger
}
func init() {
registerCollector("boottime", defaultEnabled, newBootTimeCollector)
}
// newBootTimeCollector returns a new Collector exposing system boot time on BSD systems.
func newBootTimeCollector(logger log.Logger) (Collector, error) {
return &bootTimeCollector{
name: "boot_time_seconds",
description: "Unix time of last boot, including microseconds.",
logger: logger,
}, nil
}
// Update pushes boot time onto ch
func (c *bootTimeCollector) Update(ch chan<- prometheus.Metric) error {
raw, err := unix.SysctlRaw("kern.boottime")
if err != nil {
return err
}
tv := *(*unix.Timeval)(unsafe.Pointer(&raw[0]))
v := (float64(tv.Sec) + (float64(tv.Usec) / float64(1000*1000)))
ch <- prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "", c.name),
c.description,
nil, nil,
), prometheus.GaugeValue, v)
return nil
}

View File

@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build openbsd,!amd64
// +build !nocpu // +build !nocpu
package collector package collector

View File

@ -0,0 +1,95 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !nocpu
package collector
import (
"strconv"
"unsafe"
"github.com/go-kit/kit/log"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/unix"
)
type clockinfo struct {
hz int32
tick int32
tickadj int32
stathz int32
profhz int32
}
const (
CP_USER = iota
CP_NICE
CP_SYS
CP_SPIN
CP_INTR
CP_IDLE
CPUSTATES
)
type cpuCollector struct {
cpu typedDesc
logger log.Logger
}
func init() {
registerCollector("cpu", defaultEnabled, NewCPUCollector)
}
func NewCPUCollector(logger log.Logger) (Collector, error) {
return &cpuCollector{
cpu: typedDesc{nodeCPUSecondsDesc, prometheus.CounterValue},
logger: logger,
}, nil
}
func (c *cpuCollector) Update(ch chan<- prometheus.Metric) (err error) {
clockb, err := unix.SysctlRaw("kern.clockrate")
if err != nil {
return err
}
clock := *(*clockinfo)(unsafe.Pointer(&clockb[0]))
hz := float64(clock.stathz)
ncpus, err := unix.SysctlUint32("hw.ncpu")
if err != nil {
return err
}
var cpTime [][CPUSTATES]int64
for i := 0; i < int(ncpus); i++ {
cpb, err := unix.SysctlRaw("kern.cp_time2", i)
if err != nil && err != unix.ENODEV {
return err
}
if err != unix.ENODEV {
cpTime = append(cpTime, *(*[CPUSTATES]int64)(unsafe.Pointer(&cpb[0])))
}
}
for cpu, time := range cpTime {
lcpu := strconv.Itoa(cpu)
ch <- c.cpu.mustNewConstMetric(float64(time[CP_USER])/hz, lcpu, "user")
ch <- c.cpu.mustNewConstMetric(float64(time[CP_NICE])/hz, lcpu, "nice")
ch <- c.cpu.mustNewConstMetric(float64(time[CP_SYS])/hz, lcpu, "system")
ch <- c.cpu.mustNewConstMetric(float64(time[CP_SPIN])/hz, lcpu, "spin")
ch <- c.cpu.mustNewConstMetric(float64(time[CP_INTR])/hz, lcpu, "interrupt")
ch <- c.cpu.mustNewConstMetric(float64(time[CP_IDLE])/hz, lcpu, "idle")
}
return err
}

View File

@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build openbsd,!amd64
// +build !nodiskstats // +build !nodiskstats
package collector package collector

View File

@ -0,0 +1,89 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !nodiskstats
package collector
import (
"unsafe"
"github.com/go-kit/kit/log"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/unix"
)
const (
DS_DISKNAMELEN = 16
)
type DiskStats struct {
Name [DS_DISKNAMELEN]int8
Busy int32
Rxfer uint64
Wxfer uint64
Seek uint64
Rbytes uint64
Wbytes uint64
Attachtime unix.Timeval
Timestamp unix.Timeval
Time unix.Timeval
}
type diskstatsCollector struct {
rxfer typedDesc
rbytes typedDesc
wxfer typedDesc
wbytes typedDesc
time typedDesc
logger log.Logger
}
func init() {
registerCollector("diskstats", defaultEnabled, NewDiskstatsCollector)
}
// NewDiskstatsCollector returns a new Collector exposing disk device stats.
func NewDiskstatsCollector(logger log.Logger) (Collector, error) {
return &diskstatsCollector{
rxfer: typedDesc{readsCompletedDesc, prometheus.CounterValue},
rbytes: typedDesc{readBytesDesc, prometheus.CounterValue},
wxfer: typedDesc{writesCompletedDesc, prometheus.CounterValue},
wbytes: typedDesc{writtenBytesDesc, prometheus.CounterValue},
time: typedDesc{ioTimeSecondsDesc, prometheus.CounterValue},
logger: logger,
}, nil
}
func (c *diskstatsCollector) Update(ch chan<- prometheus.Metric) (err error) {
diskstatsb, err := unix.SysctlRaw("hw.diskstats")
if err != nil {
return err
}
ndisks := len(diskstatsb) / int(unsafe.Sizeof(DiskStats{}))
diskstats := *(*[]DiskStats)(unsafe.Pointer(&diskstatsb))
for i := 0; i < ndisks; i++ {
dn := *(*[DS_DISKNAMELEN]int8)(unsafe.Pointer(&diskstats[i].Name[0]))
diskname := int8ToString(dn[:])
ch <- c.rxfer.mustNewConstMetric(float64(diskstats[i].Rxfer), diskname)
ch <- c.rbytes.mustNewConstMetric(float64(diskstats[i].Rbytes), diskname)
ch <- c.wxfer.mustNewConstMetric(float64(diskstats[i].Wxfer), diskname)
ch <- c.wbytes.mustNewConstMetric(float64(diskstats[i].Wbytes), diskname)
time := float64(diskstats[i].Time.Sec) + float64(diskstats[i].Time.Usec)/1000000
ch <- c.time.mustNewConstMetric(time, diskname)
}
return nil
}

View File

@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build openbsd darwin,amd64 dragonfly // +build openbsd,!amd64 darwin,amd64 dragonfly
// +build !nofilesystem // +build !nofilesystem
package collector package collector

View File

@ -73,7 +73,7 @@ func NewFilesystemCollector(logger log.Logger) (Collector, error) {
subsystem := "filesystem" subsystem := "filesystem"
level.Info(logger).Log("msg", "Parsed flag --collector.filesystem.ignored-mount-points", "flag", *ignoredMountPoints) level.Info(logger).Log("msg", "Parsed flag --collector.filesystem.ignored-mount-points", "flag", *ignoredMountPoints)
mountPointPattern := regexp.MustCompile(*ignoredMountPoints) mountPointPattern := regexp.MustCompile(*ignoredMountPoints)
level.Info(logger).Log("msg", "Parsed flag --collector.filesystem.ignored-fs-types", "flag", *ignoredMountPoints) level.Info(logger).Log("msg", "Parsed flag --collector.filesystem.ignored-fs-types", "flag", *ignoredFSTypes)
filesystemsTypesPattern := regexp.MustCompile(*ignoredFSTypes) filesystemsTypesPattern := regexp.MustCompile(*ignoredFSTypes)
sizeDesc := prometheus.NewDesc( sizeDesc := prometheus.NewDesc(

View File

@ -0,0 +1,77 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build openbsd darwin,amd64 dragonfly
// +build !nofilesystem
package collector
import (
"github.com/go-kit/kit/log/level"
"golang.org/x/sys/unix"
)
const (
defIgnoredMountPoints = "^/(dev)($|/)"
defIgnoredFSTypes = "^devfs$"
)
// Expose filesystem fullness.
func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) {
var mnt []unix.Statfs_t
size, err := unix.Getfsstat(mnt, unix.MNT_NOWAIT)
if err != nil {
return nil, err
}
mnt = make([]unix.Statfs_t, size)
_, err = unix.Getfsstat(mnt, unix.MNT_NOWAIT)
if err != nil {
return nil, err
}
stats = []filesystemStats{}
for _, v := range mnt {
mountpoint := int8ToString(v.F_mntonname[:])
if c.ignoredMountPointsPattern.MatchString(mountpoint) {
level.Debug(c.logger).Log("msg", "Ignoring mount point", "mountpoint", mountpoint)
continue
}
device := int8ToString(v.F_mntfromname[:])
fstype := int8ToString(v.F_fstypename[:])
if c.ignoredFSTypesPattern.MatchString(fstype) {
level.Debug(c.logger).Log("msg", "Ignoring fs type", "type", fstype)
continue
}
var ro float64
if (v.F_flags & unix.MNT_RDONLY) != 0 {
ro = 1
}
stats = append(stats, filesystemStats{
labels: filesystemLabels{
device: device,
mountPoint: mountpoint,
fsType: fstype,
},
size: float64(v.F_blocks) * float64(v.F_bsize),
free: float64(v.F_bfree) * float64(v.F_bsize),
avail: float64(v.F_bavail) * float64(v.F_bsize),
files: float64(v.F_files),
filesFree: float64(v.F_ffree),
ro: ro,
})
}
return stats, nil
}

View File

@ -3827,6 +3827,20 @@ node_zfs_zpool_rtime{zpool="poolz1"} 9.82909164e+09
# TYPE node_zfs_zpool_rupdate untyped # TYPE node_zfs_zpool_rupdate untyped
node_zfs_zpool_rupdate{zpool="pool1"} 7.921048984922e+13 node_zfs_zpool_rupdate{zpool="pool1"} 7.921048984922e+13
node_zfs_zpool_rupdate{zpool="poolz1"} 1.10734831944501e+14 node_zfs_zpool_rupdate{zpool="poolz1"} 1.10734831944501e+14
# HELP node_zfs_zpool_state kstat.zfs.misc.state
# TYPE node_zfs_zpool_state gauge
node_zfs_zpool_state{state="degraded",zpool="pool1"} 0
node_zfs_zpool_state{state="degraded",zpool="poolz1"} 1
node_zfs_zpool_state{state="faulted",zpool="pool1"} 0
node_zfs_zpool_state{state="faulted",zpool="poolz1"} 0
node_zfs_zpool_state{state="offline",zpool="pool1"} 0
node_zfs_zpool_state{state="offline",zpool="poolz1"} 0
node_zfs_zpool_state{state="online",zpool="pool1"} 1
node_zfs_zpool_state{state="online",zpool="poolz1"} 0
node_zfs_zpool_state{state="removed",zpool="pool1"} 0
node_zfs_zpool_state{state="removed",zpool="poolz1"} 0
node_zfs_zpool_state{state="unavail",zpool="pool1"} 0
node_zfs_zpool_state{state="unavail",zpool="poolz1"} 0
# HELP node_zfs_zpool_wcnt kstat.zfs.misc.io.wcnt # HELP node_zfs_zpool_wcnt kstat.zfs.misc.io.wcnt
# TYPE node_zfs_zpool_wcnt untyped # TYPE node_zfs_zpool_wcnt untyped
node_zfs_zpool_wcnt{zpool="pool1"} 0 node_zfs_zpool_wcnt{zpool="pool1"} 0

View File

@ -0,0 +1 @@
ONLINE

View File

@ -0,0 +1 @@
DEGRADED

View File

@ -79,6 +79,10 @@ func NewInfiniBandCollector(logger log.Logger) (Collector, error) {
"state_id": "State of the InfiniBand port (0: no change, 1: down, 2: init, 3: armed, 4: active, 5: act defer)", "state_id": "State of the InfiniBand port (0: no change, 1: down, 2: init, 3: armed, 4: active, 5: act defer)",
"unicast_packets_received_total": "Number of unicast packets received (including errors)", "unicast_packets_received_total": "Number of unicast packets received (including errors)",
"unicast_packets_transmitted_total": "Number of unicast packets transmitted (including errors)", "unicast_packets_transmitted_total": "Number of unicast packets transmitted (including errors)",
"port_receive_remote_physical_errors_total": "Number of packets marked with the EBP (End of Bad Packet) delimiter received on the port.",
"port_receive_switch_relay_errors_total": "Number of packets that could not be forwarded by the switch.",
"symbol_error_total": "Number of minor link errors detected on one or more physical lanes.",
"vl15_dropped_total": "Number of incoming VL15 packets dropped due to resource limitations.",
} }
i.metricDescs = make(map[string]*prometheus.Desc) i.metricDescs = make(map[string]*prometheus.Desc)
@ -157,6 +161,10 @@ func (c *infinibandCollector) Update(ch chan<- prometheus.Metric) error {
c.pushCounter(ch, "port_transmit_wait_total", port.Counters.PortXmitWait, port.Name, portStr) c.pushCounter(ch, "port_transmit_wait_total", port.Counters.PortXmitWait, port.Name, portStr)
c.pushCounter(ch, "unicast_packets_received_total", port.Counters.UnicastRcvPackets, port.Name, portStr) c.pushCounter(ch, "unicast_packets_received_total", port.Counters.UnicastRcvPackets, port.Name, portStr)
c.pushCounter(ch, "unicast_packets_transmitted_total", port.Counters.UnicastXmitPackets, port.Name, portStr) c.pushCounter(ch, "unicast_packets_transmitted_total", port.Counters.UnicastXmitPackets, port.Name, portStr)
c.pushCounter(ch, "port_receive_remote_physical_errors_total", port.Counters.PortRcvRemotePhysicalErrors, port.Name, portStr)
c.pushCounter(ch, "port_receive_switch_relay_errors_total", port.Counters.PortRcvSwitchRelayErrors, port.Name, portStr)
c.pushCounter(ch, "symbol_error_total", port.Counters.SymbolError, port.Name, portStr)
c.pushCounter(ch, "vl15_dropped_total", port.Counters.VL15Dropped, port.Name, portStr)
} }
} }

View File

@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build openbsd,!amd64
// +build !nointerrupts // +build !nointerrupts
package collector package collector

View File

@ -0,0 +1,109 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !nointerrupts
package collector
import (
"fmt"
"strconv"
"unsafe"
"github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/unix"
)
const (
KERN_INTRCNT = 63
KERN_INTRCNT_NUM = 1
KERN_INTRCNT_CNT = 2
KERN_INTRCNT_NAME = 3
KERN_INTRCNT_VECTOR = 4
)
func nintr() _C_int {
mib := [3]_C_int{unix.CTL_KERN, KERN_INTRCNT, KERN_INTRCNT_NUM}
buf, err := sysctl(mib[:])
if err != nil {
return 0
}
return *(*_C_int)(unsafe.Pointer(&buf[0]))
}
func intr(idx _C_int) (itr interrupt, err error) {
mib := [4]_C_int{unix.CTL_KERN, KERN_INTRCNT, KERN_INTRCNT_NAME, idx}
buf, err := sysctl(mib[:])
if err != nil {
return
}
dev := *(*[128]byte)(unsafe.Pointer(&buf[0]))
itr.device = string(dev[:])
mib[2] = KERN_INTRCNT_VECTOR
buf, err = sysctl(mib[:])
if err != nil {
return
}
itr.vector = *(*int)(unsafe.Pointer(&buf[0]))
mib[2] = KERN_INTRCNT_CNT
buf, err = sysctl(mib[:])
if err != nil {
return
}
count := *(*uint64)(unsafe.Pointer(&buf[0]))
itr.values = []float64{float64(count)}
return
}
var interruptLabelNames = []string{"cpu", "type", "devices"}
func (c *interruptsCollector) Update(ch chan<- prometheus.Metric) error {
interrupts, err := getInterrupts()
if err != nil {
return fmt.Errorf("couldn't get interrupts: %s", err)
}
for dev, interrupt := range interrupts {
for cpuNo, value := range interrupt.values {
ch <- c.desc.mustNewConstMetric(
value,
strconv.Itoa(cpuNo),
fmt.Sprintf("%d", interrupt.vector),
dev,
)
}
}
return nil
}
type interrupt struct {
vector int
device string
values []float64
}
func getInterrupts() (map[string]interrupt, error) {
var interrupts = map[string]interrupt{}
n := nintr()
for i := _C_int(0); i < n; i++ {
itr, err := intr(i)
if err != nil {
return nil, err
}
interrupts[itr.device] = itr
}
return interrupts, nil
}

View File

@ -11,7 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build openbsd // +build openbsd,!amd64
// +build !nomeminfo // +build !nomeminfo
package collector package collector

View File

@ -0,0 +1,44 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !nomeminfo
package collector
import (
"golang.org/x/sys/unix"
"unsafe"
)
func (c *meminfoCollector) getMemInfo() (map[string]float64, error) {
uvmexpb, err := unix.SysctlRaw("vm.uvmexp")
if err != nil {
return nil, err
}
uvmexp := *(*unix.Uvmexp)(unsafe.Pointer(&uvmexpb[0]))
ps := float64(uvmexp.Pagesize)
// see uvm(9)
return map[string]float64{
"active_bytes": ps * float64(uvmexp.Active),
"cache_bytes": ps * float64(uvmexp.Vnodepages),
"free_bytes": ps * float64(uvmexp.Free),
"inactive_bytes": ps * float64(uvmexp.Inactive),
"size_bytes": ps * float64(uvmexp.Npages),
"swap_size_bytes": ps * float64(uvmexp.Swpages),
"swap_used_bytes": ps * float64(uvmexp.Swpginuse),
"swapped_in_pages_bytes_total": ps * float64(uvmexp.Pgswapin),
"swapped_out_pages_bytes_total": ps * float64(uvmexp.Pgswapout),
"wired_bytes": ps * float64(uvmexp.Wired),
}, nil
}

View File

@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// +build openbsd,!amd64
// +build !nonetdev // +build !nonetdev
package collector package collector

View File

@ -0,0 +1,78 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !nonetdev
package collector
import (
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"golang.org/x/sys/unix"
"regexp"
"unsafe"
)
func getNetDevStats(ignore *regexp.Regexp, accept *regexp.Regexp, logger log.Logger) (netDevStats, error) {
netDev := netDevStats{}
mib := [6]_C_int{unix.CTL_NET, unix.AF_ROUTE, 0, 0, unix.NET_RT_IFLIST, 0}
buf, err := sysctl(mib[:])
if err != nil {
return nil, err
}
n := uintptr(len(buf))
index := uintptr(unsafe.Pointer(&buf[0]))
next := uintptr(0)
var rtm *unix.RtMsghdr
for next = index; next < (index + n); next += uintptr(rtm.Msglen) {
rtm = (*unix.RtMsghdr)(unsafe.Pointer(next))
if rtm.Version != unix.RTM_VERSION || rtm.Type != unix.RTM_IFINFO {
continue
}
ifm := (*unix.IfMsghdr)(unsafe.Pointer(next))
if ifm.Addrs&unix.RTA_IFP == 0 {
continue
}
dl := (*unix.RawSockaddrDatalink)(unsafe.Pointer(next + uintptr(rtm.Hdrlen)))
if dl.Family != unix.AF_LINK {
continue
}
data := ifm.Data
dev := int8ToString(dl.Data[:dl.Nlen])
if ignore != nil && ignore.MatchString(dev) {
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
continue
}
if accept != nil && !accept.MatchString(dev) {
level.Debug(logger).Log("msg", "Ignoring device", "device", dev)
continue
}
netDev[dev] = map[string]uint64{
"receive_packets": data.Ipackets,
"transmit_packets": data.Opackets,
"receive_errs": data.Ierrors,
"transmit_errs": data.Oerrors,
"receive_bytes": data.Ibytes,
"transmit_bytes": data.Obytes,
"receive_multicast": data.Imcasts,
"transmit_multicast": data.Omcasts,
"receive_drop": data.Iqdrops,
}
}
return netDev, nil
}

View File

@ -0,0 +1,86 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package collector
import (
"golang.org/x/sys/unix"
"syscall"
"unsafe"
)
func int8ToString(a []int8) string {
buf := make([]byte, len(a))
for i, v := range a {
if byte(v) == 0 {
buf = buf[:i]
break
}
buf[i] = byte(v)
}
return string(buf)
}
// unix._C_int
type _C_int int32
var _zero uintptr
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return nil
case unix.EAGAIN:
return syscall.EAGAIN
case unix.EINVAL:
return syscall.EINVAL
case unix.ENOENT:
return syscall.ENOENT
}
return e
}
func _sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
var _p0 unsafe.Pointer
if len(mib) > 0 {
_p0 = unsafe.Pointer(&mib[0])
} else {
_p0 = unsafe.Pointer(&_zero)
}
for {
_, _, e1 := unix.Syscall6(unix.SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen))
if e1 != 0 {
err = errnoErr(e1)
}
if err != unix.EINTR {
return
}
}
return
}
func sysctl(mib []_C_int) ([]byte, error) {
n := uintptr(0)
if err := _sysctl(mib, nil, &n, nil, 0); err != nil {
return nil, err
}
if n == 0 {
return nil, nil
}
buf := make([]byte, n)
if err := _sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return nil, err
}
return buf[:n], nil
}

View File

@ -17,9 +17,12 @@
package collector package collector
import ( import (
"errors"
"fmt" "fmt"
"os"
"github.com/go-kit/kit/log" "github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -163,6 +166,10 @@ func (c *timexCollector) Update(ch chan<- prometheus.Metric) error {
status, err := unix.Adjtimex(timex) status, err := unix.Adjtimex(timex)
if err != nil { if err != nil {
if errors.Is(err, os.ErrPermission) {
level.Debug(c.logger).Log("msg", "Not collecting timex metrics", "err", err)
return ErrNoData
}
return fmt.Errorf("failed to retrieve adjtimex stats: %w", err) return fmt.Errorf("failed to retrieve adjtimex stats: %w", err)
} }

View File

@ -37,6 +37,7 @@ type zfsCollector struct {
linuxProcpathBase string linuxProcpathBase string
linuxZpoolIoPath string linuxZpoolIoPath string
linuxZpoolObjsetPath string linuxZpoolObjsetPath string
linuxZpoolStatePath string
linuxPathMap map[string]string linuxPathMap map[string]string
logger log.Logger logger log.Logger
} }
@ -47,6 +48,7 @@ func NewZFSCollector(logger log.Logger) (Collector, error) {
linuxProcpathBase: "spl/kstat/zfs", linuxProcpathBase: "spl/kstat/zfs",
linuxZpoolIoPath: "/*/io", linuxZpoolIoPath: "/*/io",
linuxZpoolObjsetPath: "/*/objset-*", linuxZpoolObjsetPath: "/*/objset-*",
linuxZpoolStatePath: "/*/state",
linuxPathMap: map[string]string{ linuxPathMap: map[string]string{
"zfs_abd": "abdstats", "zfs_abd": "abdstats",
"zfs_arc": "arcstats", "zfs_arc": "arcstats",
@ -132,3 +134,18 @@ func (c *zfsCollector) constPoolObjsetMetric(poolName string, datasetName string
datasetName, datasetName,
) )
} }
func (c *zfsCollector) constPoolStateMetric(poolName string, stateName string, isActive uint64) prometheus.Metric {
return prometheus.MustNewConstMetric(
prometheus.NewDesc(
prometheus.BuildFQName(namespace, "zfs_zpool", "state"),
"kstat.zfs.misc.state",
[]string{"zpool", "state"},
nil,
),
prometheus.GaugeValue,
float64(isActive),
poolName,
stateName,
)
}

View File

@ -41,6 +41,8 @@ const (
// kstatDataString = "7" // kstatDataString = "7"
) )
var zfsPoolStatesName = []string{"online", "degraded", "faulted", "offline", "removed", "unavail"}
func (c *zfsCollector) openProcFile(path string) (*os.File, error) { func (c *zfsCollector) openProcFile(path string) (*os.File, error) {
file, err := os.Open(procFilePath(path)) file, err := os.Open(procFilePath(path))
if err != nil { if err != nil {
@ -97,10 +99,6 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
return err return err
} }
if zpoolObjsetPaths == nil {
return nil
}
for _, zpoolPath := range zpoolObjsetPaths { for _, zpoolPath := range zpoolObjsetPaths {
file, err := os.Open(zpoolPath) file, err := os.Open(zpoolPath)
if err != nil { if err != nil {
@ -117,6 +115,34 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
return err return err
} }
} }
zpoolStatePaths, err := filepath.Glob(procFilePath(filepath.Join(c.linuxProcpathBase, c.linuxZpoolStatePath)))
if err != nil {
return err
}
if zpoolStatePaths == nil {
level.Warn(c.logger).Log("msg", "Not found pool state files")
}
for _, zpoolPath := range zpoolStatePaths {
file, err := os.Open(zpoolPath)
if err != nil {
// this file should exist, but there is a race where an exporting pool can remove the files -- ok to ignore
level.Debug(c.logger).Log("msg", "Cannot open file for reading", "path", zpoolPath)
return errZFSNotAvailable
}
err = c.parsePoolStateFile(file, zpoolPath, func(poolName string, stateName string, isActive uint64) {
ch <- c.constPoolStateMetric(poolName, stateName, isActive)
})
file.Close()
if err != nil {
return err
}
}
return nil return nil
} }
@ -235,3 +261,35 @@ func (c *zfsCollector) parsePoolObjsetFile(reader io.Reader, zpoolPath string, h
return scanner.Err() return scanner.Err()
} }
func (c *zfsCollector) parsePoolStateFile(reader io.Reader, zpoolPath string, handler func(string, string, uint64)) error {
scanner := bufio.NewScanner(reader)
scanner.Scan()
actualStateName, err := scanner.Text(), scanner.Err()
if err != nil {
return err
}
actualStateName = strings.ToLower(actualStateName)
zpoolPathElements := strings.Split(zpoolPath, "/")
pathLen := len(zpoolPathElements)
if pathLen < 2 {
return fmt.Errorf("zpool path did not return at least two elements")
}
zpoolName := zpoolPathElements[pathLen-2]
for _, stateName := range zfsPoolStatesName {
isActive := uint64(0)
if actualStateName == stateName {
isActive = 1
}
handler(zpoolName, stateName, isActive)
}
return nil
}

View File

@ -494,3 +494,52 @@ func TestVdevMirrorstatsParsing(t *testing.T) {
t.Fatal("VdevMirrorStats parsing handler was not called for some expected sysctls") t.Fatal("VdevMirrorStats parsing handler was not called for some expected sysctls")
} }
} }
func TestPoolStateParsing(t *testing.T) {
zpoolPaths, err := filepath.Glob("fixtures/proc/spl/kstat/zfs/*/state")
if err != nil {
t.Fatal(err)
}
c := zfsCollector{}
if err != nil {
t.Fatal(err)
}
handlerCalled := false
for _, zpoolPath := range zpoolPaths {
file, err := os.Open(zpoolPath)
if err != nil {
t.Fatal(err)
}
err = c.parsePoolStateFile(file, zpoolPath, func(poolName string, stateName string, isActive uint64) {
handlerCalled = true
if poolName == "pool1" {
if isActive != uint64(1) && stateName == "online" {
t.Fatalf("Incorrect parsed value for online state")
}
if isActive != uint64(0) && stateName != "online" {
t.Fatalf("Incorrect parsed value for online state")
}
}
if poolName == "poolz1" {
if isActive != uint64(1) && stateName == "degraded" {
t.Fatalf("Incorrect parsed value for degraded state")
}
if isActive != uint64(0) && stateName != "degraded" {
t.Fatalf("Incorrect parsed value for degraded state")
}
}
})
file.Close()
if err != nil {
t.Fatal(err)
}
}
if !handlerCalled {
t.Fatal("Zpool parsing handler was not called for some expected sysctls")
}
}

6
go.mod
View File

@ -12,22 +12,20 @@ require (
github.com/mattn/go-xmlrpc v0.0.3 github.com/mattn/go-xmlrpc v0.0.3
github.com/mdlayher/genetlink v1.0.0 // indirect github.com/mdlayher/genetlink v1.0.0 // indirect
github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd github.com/mdlayher/wifi v0.0.0-20200527114002-84f0b9457fdd
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.7.1 github.com/prometheus/client_golang v1.7.1
github.com/prometheus/client_model v0.2.0 github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.14.0 github.com/prometheus/common v0.15.0
github.com/prometheus/exporter-toolkit v0.5.0
github.com/prometheus/procfs v0.2.0 github.com/prometheus/procfs v0.2.0
github.com/siebenmann/go-kstat v0.0.0-20200303194639-4e8294f9e9d5 github.com/siebenmann/go-kstat v0.0.0-20200303194639-4e8294f9e9d5
github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a
go.uber.org/multierr v1.5.0 // indirect go.uber.org/multierr v1.5.0 // indirect
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb // indirect
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a // indirect
golang.org/x/sys v0.0.0-20201202213521-69691e467435 golang.org/x/sys v0.0.0-20201202213521-69691e467435
golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 // indirect golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v2 v2.3.0
honnef.co/go/tools v0.0.1-2020.1.3 // indirect honnef.co/go/tools v0.0.1-2020.1.3 // indirect
) )

22
go.sum
View File

@ -290,8 +290,10 @@ github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLy
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.14.0 h1:RHRyE8UocrbjU+6UvRzwi6HjiDfxrrBU91TtbKzkGp4= github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM=
github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/exporter-toolkit v0.5.0 h1:GwrxhCviqOl8Mm0vKqkh7Xy54m+FPlHEJacFs48M3gY=
github.com/prometheus/exporter-toolkit v0.5.0/go.mod h1:OCkM4805mmisBhLmVFw858QYi3v0wKdY6/UxrT0pZVg=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
@ -367,8 +369,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM= golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -446,6 +448,7 @@ golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzC
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -453,12 +456,9 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860 h1:YEu4SMq7D0cmT7CBbXfcH0NZeuChAXwsHe/9XueUO6o=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634 h1:bNEHhJCnrwMKNMmOx3yAynp5vs5/gRy+XWFtZFu7NBM= golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20201118182958-a01c418693c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -537,6 +537,8 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@ -1,81 +0,0 @@
# HTTPS Package for Prometheus
The `https` directory contains a Go package and a sample configuration file for
running `node_exporter` with HTTPS instead of HTTP. We currently support TLS 1.3
and TLS 1.2.
To run a server with TLS, use the flag `--web.config`.
e.g. `./node_exporter --web.config="web-config.yml"`
If the config is kept within the https directory.
The config file should be written in YAML format, and is reloaded on each connection to check for new certificates and/or authentication policy.
## Sample Config
```
tls_server_config:
# Certificate and key files for server to use to authenticate to client.
cert_file: <filename>
key_file: <filename>
# Server policy for client authentication. Maps to ClientAuth Policies.
# For more detail on clientAuth options: [ClientAuthType](https://golang.org/pkg/crypto/tls/#ClientAuthType)
[ client_auth_type: <string> | default = "NoClientCert" ]
# CA certificate for client certificate authentication to the server.
[ client_ca_file: <filename> ]
# Minimum TLS version that is acceptable.
[ min_version: <string> | default = "TLS12" ]
# Maximum TLS version that is acceptable.
[ max_version: <string> | default = "TLS13" ]
# List of supported cipher suites for TLS versions up to TLS 1.2. If empty,
# Go default cipher suites are used. Available cipher suites are documented
# in the go documentation:
# https://golang.org/pkg/crypto/tls/#pkg-constants
[ cipher_suites:
[ - <string> ] ]
# prefer_server_cipher_suites controls whether the server selects the
# client's most preferred ciphersuite, or the server's most preferred
# ciphersuite. If true then the server's preference, as expressed in
# the order of elements in cipher_suites, is used.
[ prefer_server_cipher_suites: <bool> | default = true ]
# Elliptic curves that will be used in an ECDHE handshake, in preference
# order. Available curves are documented in the go documentation:
# https://golang.org/pkg/crypto/tls/#CurveID
[ curve_preferences:
[ - <string> ] ]
http_server_config:
# Enable HTTP/2 support. Note that HTTP/2 is only supported with TLS.
# This can not be changed on the fly.
[ http2: <bool> | default = true ]
# Usernames and hashed passwords that have full access to the web
# server via basic authentication. If empty, no basic authentication is
# required. Passwords are hashed with bcrypt.
basic_auth_users:
[ <string>: <secret> ... ]
```
## About bcrypt
There are several tools out there to generate bcrypt passwords, e.g.
[htpasswd](https://httpd.apache.org/docs/2.4/programs/htpasswd.html):
`htpasswd -nBC 10 "" | tr -d ':\n'`
That command will prompt you for a password and output the hashed password,
which will look something like:
`$2y$10$X0h1gDsPszWURQaxFh.zoubFi6DXncSjhoQNJgRrnGs7EsimhC7zG`
The cost (10 in the example) influences the time it takes for computing the
hash. A higher cost will en up slowing down the authentication process.
Depending on the machine, a cost of 10 will take about ~70ms where a cost of
18 can take up to a few seconds. That hash will be computed on every
password-protected request.

View File

@ -1,96 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus TLS CA
Validity
Not Before: Apr 5 08:06:57 2019 GMT
Not After : Mar 26 08:06:57 2059 GMT
Subject: C=US, O=Prometheus, CN=prometheus.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:bd:6c:b6:7f:d1:2f:be:e4:41:eb:5d:ff:50:78:
03:2b:76:03:da:01:48:20:13:90:66:c9:ce:6e:06:
e5:fa:2d:0d:c0:b0:46:28:44:10:a0:61:79:87:a2:
98:4c:29:fa:f9:bb:0f:44:c7:90:5c:5c:55:60:cd:
45:da:b8:e4:dd:28:72:c8:8b:a1:3e:4b:00:09:82:
b0:2c:dc:d6:17:c9:02:f4:cd:26:c7:11:28:f3:77:
b5:97:c2:76:c2:e0:07:d7:34:5b:e0:ed:1a:59:a5:
b4:b7:16:09:3d:35:bd:d9:03:07:9d:7c:3b:f0:63:
bd:5e:02:99:cf:32:e1:ac:4c:7a:3e:4c:b2:8e:98:
68:07:4f:59:dc:0d:bf:cc:83:04:5c:d8:90:f0:73:
da:2b:08:17:c4:36:a7:d8:94:3d:b6:c0:af:29:0a:
d3:19:5f:eb:7d:cc:4d:05:56:11:0a:ee:b1:f3:d7:
c9:5a:3c:8c:57:16:91:51:14:f8:20:4e:0f:29:9e:
04:21:e6:f1:e4:e8:44:af:d7:25:92:08:64:fc:2c:
1c:2e:4f:71:53:91:53:1d:e5:f9:7b:52:0f:21:da:
5c:dd:19:68:96:ca:70:6a:f1:c4:0d:07:af:f8:65:
13:92:e9:ef:65:b3:89:86:fd:c0:74:5c:a4:6b:49:
62:c5
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Basic Constraints:
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Subject Key Identifier:
00:61:01:AD:25:44:8A:EF:E1:2C:EC:83:5A:3A:3B:EA:A0:BD:E1:45
X509v3 Authority Key Identifier:
keyid:4D:02:BF:71:95:6A:AA:58:C5:9C:B8:83:67:5E:64:16:99:E1:2A:9E
Authority Information Access:
CA Issuers - URI:http://example.com/ca/tls-ca.cer
X509v3 CRL Distribution Points:
Full Name:
URI:http://example.com/ca/tls-ca.crl
X509v3 Subject Alternative Name:
IP Address:127.0.0.1, IP Address:127.0.0.0, DNS:localhost
Signature Algorithm: sha1WithRSAEncryption
77:97:e4:ef:db:10:8e:62:50:96:4a:6e:f5:a4:f9:1f:19:3b:
c8:a4:dd:b3:f6:11:41:1a:fb:e3:f8:dd:0e:64:e5:2b:00:b9:
e6:25:9f:2e:e1:d2:9a:cd:b6:f2:41:4d:27:dd:2c:9a:af:97:
79:e8:cf:61:fb:cf:be:25:c6:e1:19:a0:c8:90:44:a0:76:8a:
45:d4:37:22:e5:d4:80:b4:b3:0f:a8:33:08:24:ad:21:0b:b7:
98:46:93:90:8a:ae:77:0c:cb:b8:59:d3:3b:9b:fb:16:5a:22:
ca:c2:97:9d:78:1b:fc:23:fc:a0:42:54:40:de:88:4b:07:2b:
19:4e:0e:79:bf:c9:9f:01:a6:46:c5:55:fa:9f:c0:0d:8a:a6:
e1:47:16:a6:0e:be:23:c9:e9:58:d6:31:71:8c:80:9c:16:64:
f0:14:08:22:a1:23:7c:98:b9:62:d1:4a:ce:e3:5c:59:fb:41:
87:a5:3b:36:dd:3d:45:48:b0:b0:77:6f:de:58:2a:27:4d:56:
20:54:08:20:c8:6d:79:b5:b9:e6:3a:03:24:0f:6d:67:39:20:
78:10:2f:47:85:83:c1:4d:17:33:79:84:75:27:fa:47:67:59:
56:cc:33:7b:a5:77:aa:59:9a:98:30:10:1a:78:43:34:8f:ed:
c2:a1:a3:ea
-----BEGIN CERTIFICATE-----
MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET
MBEGA1UECgwKUHJvbWV0aGV1czEpMCcGA1UECwwgUHJvbWV0aGV1cyBDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkxGjAYBgNVBAMMEVByb21ldGhldXMgVExTIENBMCAXDTE5
MDQwNTA4MDY1N1oYDzIwNTkwMzI2MDgwNjU3WjBDMQswCQYDVQQGEwJVUzETMBEG
A1UECgwKUHJvbWV0aGV1czEfMB0GA1UEAwwWcHJvbWV0aGV1cy5leGFtcGxlLmNv
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL1stn/RL77kQetd/1B4
Ayt2A9oBSCATkGbJzm4G5fotDcCwRihEEKBheYeimEwp+vm7D0THkFxcVWDNRdq4
5N0ocsiLoT5LAAmCsCzc1hfJAvTNJscRKPN3tZfCdsLgB9c0W+DtGlmltLcWCT01
vdkDB518O/BjvV4Cmc8y4axMej5Mso6YaAdPWdwNv8yDBFzYkPBz2isIF8Q2p9iU
PbbArykK0xlf633MTQVWEQrusfPXyVo8jFcWkVEU+CBODymeBCHm8eToRK/XJZII
ZPwsHC5PcVORUx3l+XtSDyHaXN0ZaJbKcGrxxA0Hr/hlE5Lp72WziYb9wHRcpGtJ
YsUCAwEAAaOCAREwggENMA4GA1UdDwEB/wQEAwIFoDAJBgNVHRMEAjAAMB0GA1Ud
JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHQ4EFgQUAGEBrSVEiu/hLOyD
Wjo76qC94UUwHwYDVR0jBBgwFoAUTQK/cZVqqljFnLiDZ15kFpnhKp4wPAYIKwYB
BQUHAQEEMDAuMCwGCCsGAQUFBzAChiBodHRwOi8vZXhhbXBsZS5jb20vY2EvdGxz
LWNhLmNlcjAxBgNVHR8EKjAoMCagJKAihiBodHRwOi8vZXhhbXBsZS5jb20vY2Ev
dGxzLWNhLmNybDAgBgNVHREEGTAXhwR/AAABhwR/AAAAgglsb2NhbGhvc3QwDQYJ
KoZIhvcNAQEFBQADggEBAHeX5O/bEI5iUJZKbvWk+R8ZO8ik3bP2EUEa++P43Q5k
5SsAueYlny7h0prNtvJBTSfdLJqvl3noz2H7z74lxuEZoMiQRKB2ikXUNyLl1IC0
sw+oMwgkrSELt5hGk5CKrncMy7hZ0zub+xZaIsrCl514G/wj/KBCVEDeiEsHKxlO
Dnm/yZ8BpkbFVfqfwA2KpuFHFqYOviPJ6VjWMXGMgJwWZPAUCCKhI3yYuWLRSs7j
XFn7QYelOzbdPUVIsLB3b95YKidNViBUCCDIbXm1ueY6AyQPbWc5IHgQL0eFg8FN
FzN5hHUn+kdnWVbMM3uld6pZmpgwEBp4QzSP7cKho+o=
-----END CERTIFICATE-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC9bLZ/0S++5EHr
Xf9QeAMrdgPaAUggE5Bmyc5uBuX6LQ3AsEYoRBCgYXmHophMKfr5uw9Ex5BcXFVg
zUXauOTdKHLIi6E+SwAJgrAs3NYXyQL0zSbHESjzd7WXwnbC4AfXNFvg7RpZpbS3
Fgk9Nb3ZAwedfDvwY71eApnPMuGsTHo+TLKOmGgHT1ncDb/MgwRc2JDwc9orCBfE
NqfYlD22wK8pCtMZX+t9zE0FVhEK7rHz18laPIxXFpFRFPggTg8pngQh5vHk6ESv
1yWSCGT8LBwuT3FTkVMd5fl7Ug8h2lzdGWiWynBq8cQNB6/4ZROS6e9ls4mG/cB0
XKRrSWLFAgMBAAECggEAezQ0V1o11dEc1vuiTjJgzWnLA4aF5OcUquZjb8jo2Blp
soR0fUgYEFiV9RRaPl+nr7ptKe0rBgfAOGALKUHNCdN/JNU8oQmjEoyADg3s6jeB
xruQlzWgDwszf2uqVwHj16Nkhx1wYBKZQeQBSmCkBHwl/daKHcahqn3CkLOleKx+
Qlc3BzWNaGte6qpJMs0It3by1FuxRwVz5VkL8uhzj0WIOYMA84t0gTnFH9gfRO3F
licotxg/Nl5M36wWcfL8Jq++72AtaKcD1jUEwuQpogrVeqflmeHwn/TlL++Hv6Xe
Lq0jt3OCUKUV40eq9c5uEgTmyrVHMDkfFdXzutdMAQKBgQDsSMXk7P4SX6u6uTjV
In9eWw6ZyJ2aL6VB9co/NMsj49GrrFT8VX9d+JPe9P/n6tuGcFbymNep22njRksR
0ItpW1NFRR/R3g0kYe1EhkRpNm6fhY9oIuR9xhcNnPNYkqAKT3T/dxrzbwsNhomi
X8aht/eCz4ZsK/KdOGTkPozxgQKBgQDNOvrclT1Wl4bxONp9pEV5XpRSD/qigfIp
i5wxy7ihX/QY9RToIWJDnzMVLnEYe64RB2WB8/4WwNPOQcuaxXbFUFct/2NdhTnS
ToJPgPe819zW9t1FLTf1fHtsRBpGFtbhdlUDOiOtJiMXYiwlRh2uyWFhjOo8TNUE
qMwai0vLRQKBgQCDH4t6lC4W4jK5x2oLlT5bjWqX2uXjF8e8x/q5gsGspBPKEjOD
aKrq6jSdSRbui73RaGxH6pvb7iBf+LVWKIYFLKIUUdzrqS9f3lw+Z8h1HrjbG9JO
dvaX+aL3cf71S0E3F4sU7fLt3tSiZ+PfUQk424+mbyXox6a2qwIKS9AJgQKBgHCu
dHROYJo9ojKpo5Ueb6K+4jLYYSV+sYZMCBtzHlFETNKzJaJ6SeiU7Ugw8pmdtqnU
5M/gNl8pymFR0MeOqbKWdPdlZJpBfsjQoE2kouEFqFRCwKStui7IBUAheEeJXLv3
659U+aek69l35oMkp0GDgjs8UpN/H+pp/36Hgrr9AoGAftWU405rpStHEdRVrazP
FibQesT9HOdJgmm1gNIhj+PnFs7lKER9p0Wdl79QnIqjwyhjCXL94TFerzTKLY2c
IRj5dcRHiiT0iK8wq8bzGNYCqV73oQXaUFMiutNAArXwzwuvPFPWNBQsjLzeDLeC
mcOsCcPAk8cLYtVfZo2sP3g=
-----END PRIVATE KEY-----

View File

@ -1,173 +0,0 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus Root CA
Validity
Not Before: Apr 5 08:00:37 2019 GMT
Not After : Mar 26 08:00:37 2059 GMT
Subject: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus TLS CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:aa:d2:34:6b:ed:f1:f4:01:08:e5:00:9f:75:c8:
ba:fc:4b:72:c6:04:93:af:f1:f6:b5:ce:01:0d:c6:
bd:d3:16:98:9d:e5:51:56:12:58:16:ee:18:6e:f0:
68:a9:42:16:65:cf:e3:31:f5:90:79:9d:13:32:87:
3b:1f:65:fd:84:88:a4:56:3d:26:54:69:05:27:5a:
ea:89:02:e7:31:9b:7d:7f:76:93:54:70:bc:17:92:
06:9f:9f:90:4a:8a:cf:82:a7:7b:7c:71:c4:fa:34:
56:00:32:1a:85:c5:f8:e4:4a:63:43:37:9d:60:84:
4d:78:6e:87:12:c4:2b:1f:93:a5:fe:cc:5e:f1:df:
c1:97:ff:b7:3e:20:38:1d:71:15:11:ec:6c:7a:cc:
0e:87:52:31:b1:b9:74:c3:07:1c:42:4b:1e:c1:17:
bc:e4:13:b7:b0:20:2e:c4:07:93:bd:a8:11:f9:da:
a7:d0:df:4a:48:be:9b:6d:65:c3:ae:58:56:c0:9f:
17:c5:d8:32:b1:04:22:fb:5b:18:f6:20:10:50:ec:
2d:10:4f:cc:48:8f:f2:75:dd:33:a4:0e:f5:55:da:
2c:89:a1:3a:52:bb:11:11:0b:97:27:17:73:35:da:
10:71:b3:9f:a8:42:91:e6:3a:66:00:f9:e5:11:8f:
5b:57
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE, pathlen:0
X509v3 Subject Key Identifier:
4D:02:BF:71:95:6A:AA:58:C5:9C:B8:83:67:5E:64:16:99:E1:2A:9E
X509v3 Authority Key Identifier:
keyid:3C:1E:A8:C6:4C:05:4D:20:EC:88:DB:29:D4:7B:F9:12:5D:CE:EA:1A
Authority Information Access:
CA Issuers - URI:https://example.com/ca/root-ca.cer
X509v3 CRL Distribution Points:
Full Name:
URI:https://example.com/ca/root-ca.crl
Signature Algorithm: sha1WithRSAEncryption
63:fc:ba:30:a5:05:d6:76:14:f1:77:38:b1:41:6f:81:d9:b4:
02:fd:bc:e5:f6:d9:e6:73:e0:71:cf:4c:fb:13:b5:6b:bd:b9:
c6:f6:28:18:36:e1:8c:d9:93:b3:78:4a:3d:39:1b:f4:fb:69:
75:24:ae:e1:a0:2f:94:05:bf:10:3c:3e:d2:2b:a8:f3:31:25:
2e:ed:13:ad:60:5d:22:9a:26:15:20:86:98:73:4c:f6:4b:48:
b8:1f:67:ba:4e:c9:47:ed:85:dc:38:dc:02:0c:fb:54:d5:2e:
6c:b4:95:18:51:d1:ae:ea:e8:fb:b4:19:50:04:bc:31:7e:51:
9e:85:29:4d:c8:f7:26:d6:d6:8d:35:2d:9e:e2:06:16:38:e2:
56:80:ec:f3:a3:34:e3:28:c4:e8:10:d0:8a:a6:6f:20:9a:b9:
dc:b9:90:6b:ba:8a:27:2c:29:72:28:55:e7:59:a6:a7:90:ec:
32:e8:d0:26:4a:c1:44:dd:20:bf:dc:4d:1e:7e:cc:e5:a2:5b:
e8:df:3d:4b:01:aa:48:56:17:e9:29:d8:71:83:05:36:8c:11:
4f:77:b8:95:20:b7:c7:21:06:c2:87:97:b4:6b:d3:f7:23:ba:
4d:5f:15:d1:0c:4d:6e:f1:6a:9d:57:5c:02:6a:d7:31:18:ef:
5c:fc:f8:04
-----BEGIN CERTIFICATE-----
MIIELTCCAxWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzET
MBEGA1UECgwKUHJvbWV0aGV1czEpMCcGA1UECwwgUHJvbWV0aGV1cyBDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMElByb21ldGhldXMgUm9vdCBDQTAgFw0x
OTA0MDUwODAwMzdaGA8yMDU5MDMyNjA4MDAzN1owaTELMAkGA1UEBhMCVVMxEzAR
BgNVBAoMClByb21ldGhldXMxKTAnBgNVBAsMIFByb21ldGhldXMgQ2VydGlmaWNh
dGUgQXV0aG9yaXR5MRowGAYDVQQDDBFQcm9tZXRoZXVzIFRMUyBDQTCCASIwDQYJ
KoZIhvcNAQEBBQADggEPADCCAQoCggEBAKrSNGvt8fQBCOUAn3XIuvxLcsYEk6/x
9rXOAQ3GvdMWmJ3lUVYSWBbuGG7waKlCFmXP4zH1kHmdEzKHOx9l/YSIpFY9JlRp
BSda6okC5zGbfX92k1RwvBeSBp+fkEqKz4Kne3xxxPo0VgAyGoXF+ORKY0M3nWCE
TXhuhxLEKx+Tpf7MXvHfwZf/tz4gOB1xFRHsbHrMDodSMbG5dMMHHEJLHsEXvOQT
t7AgLsQHk72oEfnap9DfSki+m21lw65YVsCfF8XYMrEEIvtbGPYgEFDsLRBPzEiP
8nXdM6QO9VXaLImhOlK7ERELlycXczXaEHGzn6hCkeY6ZgD55RGPW1cCAwEAAaOB
3DCB2TAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4E
FgQUTQK/cZVqqljFnLiDZ15kFpnhKp4wHwYDVR0jBBgwFoAUPB6oxkwFTSDsiNsp
1Hv5El3O6howPgYIKwYBBQUHAQEEMjAwMC4GCCsGAQUFBzAChiJodHRwczovL2V4
YW1wbGUuY29tL2NhL3Jvb3QtY2EuY2VyMDMGA1UdHwQsMCowKKAmoCSGImh0dHBz
Oi8vZXhhbXBsZS5jb20vY2Evcm9vdC1jYS5jcmwwDQYJKoZIhvcNAQEFBQADggEB
AGP8ujClBdZ2FPF3OLFBb4HZtAL9vOX22eZz4HHPTPsTtWu9ucb2KBg24YzZk7N4
Sj05G/T7aXUkruGgL5QFvxA8PtIrqPMxJS7tE61gXSKaJhUghphzTPZLSLgfZ7pO
yUfthdw43AIM+1TVLmy0lRhR0a7q6Pu0GVAEvDF+UZ6FKU3I9ybW1o01LZ7iBhY4
4laA7POjNOMoxOgQ0IqmbyCaudy5kGu6iicsKXIoVedZpqeQ7DLo0CZKwUTdIL/c
TR5+zOWiW+jfPUsBqkhWF+kp2HGDBTaMEU93uJUgt8chBsKHl7Rr0/cjuk1fFdEM
TW7xap1XXAJq1zEY71z8+AQ=
-----END CERTIFICATE-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus Root CA
Validity
Not Before: Apr 5 07:55:00 2019 GMT
Not After : Mar 26 07:55:00 2059 GMT
Subject: C=US, O=Prometheus, OU=Prometheus Certificate Authority, CN=Prometheus Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:bf:b9:e2:ab:5f:61:22:e1:4e:cd:ee:da:b0:26:
2e:bb:b0:7e:1c:ce:10:be:16:29:35:0c:0c:1d:93:
01:29:2a:f6:f9:c2:6e:5c:10:44:ca:f8:dc:ad:7a:
06:64:0f:8a:18:ad:b2:a2:94:49:c9:ba:8c:45:94:
7c:d9:e0:11:45:d8:16:79:a2:20:9f:8c:63:60:72:
2a:5b:f9:66:80:ac:85:67:01:5a:eb:91:c1:d2:88:
87:9e:4c:18:c9:f2:f0:7a:18:c0:e6:ab:2c:78:de:
5f:b2:22:4e:94:9c:f5:cd:e6:e2:33:30:e9:20:10:
a6:a1:75:eb:59:ab:45:a9:f7:3e:54:40:ae:05:25:
be:74:c5:3a:fd:af:73:16:60:45:7c:4a:e0:0e:0d:
a1:15:7f:9a:1f:c2:a7:04:ad:ef:b3:e4:f6:00:2c:
4e:0b:04:90:49:ee:d3:db:a6:12:c4:91:0b:32:4f:
11:84:c7:c4:8a:ef:51:66:7a:b0:20:2f:cb:95:8d:
96:57:60:66:5e:f9:4f:5a:94:9c:71:ad:eb:ca:70:
3e:62:06:c2:3a:29:f8:9e:86:af:da:07:78:f8:31:
af:42:48:49:9e:4a:df:1b:27:1f:44:35:81:6d:fa:
7a:c5:6a:0a:35:23:c7:c4:d5:fe:c9:9e:61:c9:30:
cd:1f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign, CRL Sign
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
3C:1E:A8:C6:4C:05:4D:20:EC:88:DB:29:D4:7B:F9:12:5D:CE:EA:1A
X509v3 Authority Key Identifier:
keyid:3C:1E:A8:C6:4C:05:4D:20:EC:88:DB:29:D4:7B:F9:12:5D:CE:EA:1A
Signature Algorithm: sha1WithRSAEncryption
56:2f:79:e5:12:91:f5:19:a7:d1:32:28:fd:e3:9d:8f:e1:3c:
bb:a3:a5:f2:55:8a:03:ad:2c:1d:18:82:e1:7f:19:75:d9:47:
5b:e7:7c:e4:a5:e0:eb:dc:7e:24:a3:7d:99:1a:cf:39:ba:a5:
b4:b8:45:68:83:cf:70:ad:56:f2:34:73:65:fc:6c:b0:53:9a:
79:04:f7:3e:7e:4b:22:1b:e7:76:23:20:bc:9c:05:a2:5d:01:
d2:f0:09:49:17:b2:61:74:1a:5b:f4:e0:fd:ce:11:ba:13:4a:
e6:07:11:7d:30:e2:11:87:ee:33:1a:68:de:67:f4:ac:b5:58:
1a:ac:cf:7a:2d:fd:c3:44:5b:4b:cd:6c:ff:f6:49:b4:55:4a:
09:a0:92:2d:57:3b:69:85:54:3e:e9:ec:ef:b2:a5:7a:29:75:
2b:f8:eb:4b:d4:cf:68:ee:3e:c8:63:7e:12:eb:e4:2f:63:a3:
a7:c8:0f:e9:39:ff:5c:29:65:7f:25:f0:42:bf:07:ba:06:b8:
5e:d6:56:ba:f8:67:56:1b:42:aa:b3:04:d8:6e:88:10:a5:70:
b5:81:04:a4:90:a3:f0:83:4d:0c:6b:12:5d:a4:4c:83:5a:ff:
a8:7a:86:61:ff:0f:4c:e5:0f:17:d1:64:3c:bd:d9:22:7e:b7:
fa:9b:83:ba
-----BEGIN CERTIFICATE-----
MIIDtDCCApygAwIBAgIBATANBgkqhkiG9w0BAQUFADBqMQswCQYDVQQGEwJVUzET
MBEGA1UECgwKUHJvbWV0aGV1czEpMCcGA1UECwwgUHJvbWV0aGV1cyBDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkxGzAZBgNVBAMMElByb21ldGhldXMgUm9vdCBDQTAgFw0x
OTA0MDUwNzU1MDBaGA8yMDU5MDMyNjA3NTUwMFowajELMAkGA1UEBhMCVVMxEzAR
BgNVBAoMClByb21ldGhldXMxKTAnBgNVBAsMIFByb21ldGhldXMgQ2VydGlmaWNh
dGUgQXV0aG9yaXR5MRswGQYDVQQDDBJQcm9tZXRoZXVzIFJvb3QgQ0EwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/ueKrX2Ei4U7N7tqwJi67sH4czhC+
Fik1DAwdkwEpKvb5wm5cEETK+NytegZkD4oYrbKilEnJuoxFlHzZ4BFF2BZ5oiCf
jGNgcipb+WaArIVnAVrrkcHSiIeeTBjJ8vB6GMDmqyx43l+yIk6UnPXN5uIzMOkg
EKahdetZq0Wp9z5UQK4FJb50xTr9r3MWYEV8SuAODaEVf5ofwqcEre+z5PYALE4L
BJBJ7tPbphLEkQsyTxGEx8SK71FmerAgL8uVjZZXYGZe+U9alJxxrevKcD5iBsI6
Kfiehq/aB3j4Ma9CSEmeSt8bJx9ENYFt+nrFago1I8fE1f7JnmHJMM0fAgMBAAGj
YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ8
HqjGTAVNIOyI2ynUe/kSXc7qGjAfBgNVHSMEGDAWgBQ8HqjGTAVNIOyI2ynUe/kS
Xc7qGjANBgkqhkiG9w0BAQUFAAOCAQEAVi955RKR9Rmn0TIo/eOdj+E8u6Ol8lWK
A60sHRiC4X8ZddlHW+d85KXg69x+JKN9mRrPObqltLhFaIPPcK1W8jRzZfxssFOa
eQT3Pn5LIhvndiMgvJwFol0B0vAJSReyYXQaW/Tg/c4RuhNK5gcRfTDiEYfuMxpo
3mf0rLVYGqzPei39w0RbS81s//ZJtFVKCaCSLVc7aYVUPuns77Kleil1K/jrS9TP
aO4+yGN+EuvkL2Ojp8gP6Tn/XCllfyXwQr8Huga4XtZWuvhnVhtCqrME2G6IEKVw
tYEEpJCj8INNDGsSXaRMg1r/qHqGYf8PTOUPF9FkPL3ZIn63+puDug==
-----END CERTIFICATE-----

View File

@ -1,4 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_ca_file : "somefile"

View File

@ -1,4 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "RequireAndVerifyClientCert"

View File

@ -1,5 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
basic_auth_users:
john: doe

View File

View File

@ -1,20 +0,0 @@
hWkNKCp3fvIx3jKnsaBI
TuEjdwNS8A2vYdFbiKqr
ay3RiOtykgt4m6m3KOol
ZreGpJRGmpDSVV9cioiF
r7kDOHhHU2frvv0nLcY2
uQMQM4XgqFkCG6gFAIJZ
g99tTkrZhN9b6pkJ6J2y
rzdt729HrA2RblDGYfjs
MW7GxrBdlCnliYJGPhfr
g9kaXxMXcDwsw0C0rv0u
637ZmfRGElb6VBVOtgqn
RG0MRezjLYCJQBMUdRDE
RzO4VicAzj7asVZAT3oo
nPw267UONk7h7KBYRgch
Alj38foWqjV3heXXdahm
TrMzMgl6JIQ1x4OZB5i4
qlrXFJoeV6Pr77nuiEh9
3yE5vMnnKHm2nImEfzMG
bI01UDObHRSaoJLC0vTD
G9tlcKU883NkQ6nsxJ8Y

View File

@ -1,2 +0,0 @@
tls_server_config :
cert_filse: "testdata/server.crt"

View File

@ -1,4 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_ca_file : "testdata/tls-ca-chain.pem"

View File

@ -1,5 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "RequireAndVerifyClientCert"
client_ca_file: "testdata/tls-ca-chain.pem"

View File

@ -1,5 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"

View File

@ -1,26 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
cipher_suites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
- TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
- TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_3DES_EDE_CBC_SHA
- TLS_RSA_WITH_AES_128_CBC_SHA
- TLS_RSA_WITH_AES_256_CBC_SHA
- TLS_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384

View File

@ -1,10 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
curve_preferences:
- CurveP256
- CurveP384
- CurveP521
- X25519

View File

@ -1,3 +0,0 @@
tls_server_config :
cert_file : ""
key_file : "testdata/server.key"

View File

@ -1,3 +0,0 @@
tls_server_config :
cert_file : "somefile"
key_file : "testdata/server.key"

View File

@ -1,4 +0,0 @@
tls_server_config :
cert_file : ""
key_file : ""
client_auth_type: "x"

View File

@ -1,3 +0,0 @@
tls_server_config :
cert_file : "somefile"
key_file : "somefile"

View File

@ -1,8 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
cipher_suites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA2048

View File

@ -1,7 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
curve_preferences:
- CurveP257

View File

@ -1,3 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : ""

View File

@ -1,3 +0,0 @@
tls_server_config :
cert_file : "testdata/server.cert"
key_file : "somefile"

View File

@ -1,10 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
cipher_suites:
- TLS_RSA_WITH_AES_128_CBC_SHA
max_version: TLS12
http_server_config:
http2: false

View File

@ -1,8 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
cipher_suites:
- TLS_RSA_WITH_AES_128_CBC_SHA
max_version: TLS12

View File

@ -1,10 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
cipher_suites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
min_version: TLS12
max_version: TLS12

View File

@ -1,11 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
cipher_suites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
prefer_server_cipher_suites: false
min_version: TLS12
max_version: TLS12

View File

@ -1,8 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
min_version: TLS13
curve_preferences:
- CurveP521

View File

@ -1,6 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
client_auth_type : "VerifyClientCertIfGiven"
client_ca_file : "testdata/tls-ca-chain.pem"
min_version: TLS111

View File

@ -1,8 +0,0 @@
tls_server_config :
cert_file : "testdata/server.crt"
key_file : "testdata/server.key"
basic_auth_users:
alice: $2y$12$1DpfPeqF9HzHJt.EWswy1exHluGfbhnn3yXhR7Xes6m3WJqFg0Wby
bob: $2y$18$4VeFDzXIoPHKnKTU3O3GH.N.vZu06CVqczYZ8WvfzrddFU6tGqjR.
carol: $2y$10$qRTBuFoULoYNA7AQ/F3ck.trZBPyjV64.oA4ZsSBCIWvXuvQlQTuu
dave: $2y$10$2UXri9cIDdgeKjBo4Rlpx.U3ZLDV8X1IxKmsfOvhcM5oXQt/mLmXq

View File

@ -1,5 +0,0 @@
basic_auth_users:
alice: $2y$12$1DpfPeqF9HzHJt.EWswy1exHluGfbhnn3yXhR7Xes6m3WJqFg0Wby
bob: $2y$18$4VeFDzXIoPHKnKTU3O3GH.N.vZu06CVqczYZ8WvfzrddFU6tGqjR.
carol: $2y$10$qRTBuFoULoYNA7AQ/F3ck.trZBPyjV64.oA4ZsSBCIWvXuvQlQTuu
dave: $2y$10$2UXri9cIDdgeKjBo4Rlpx.U3ZLDV8X1IxKmsfOvhcM5oXQt/mLmXq

View File

@ -1,301 +0,0 @@
// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package https allows the implementation of TLS.
package https
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net/http"
"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/pkg/errors"
config_util "github.com/prometheus/common/config"
"gopkg.in/yaml.v2"
)
var (
errNoTLSConfig = errors.New("TLS config is not present")
)
type Config struct {
TLSConfig TLSStruct `yaml:"tls_server_config"`
HTTPConfig HTTPStruct `yaml:"http_server_config"`
Users map[string]config_util.Secret `yaml:"basic_auth_users"`
}
type TLSStruct struct {
TLSCertPath string `yaml:"cert_file"`
TLSKeyPath string `yaml:"key_file"`
ClientAuth string `yaml:"client_auth_type"`
ClientCAs string `yaml:"client_ca_file"`
CipherSuites []cipher `yaml:"cipher_suites"`
CurvePreferences []curve `yaml:"curve_preferences"`
MinVersion tlsVersion `yaml:"min_version"`
MaxVersion tlsVersion `yaml:"max_version"`
PreferServerCipherSuites bool `yaml:"prefer_server_cipher_suites"`
}
type HTTPStruct struct {
HTTP2 bool `yaml:"http2"`
}
func getConfig(configPath string) (*Config, error) {
content, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, err
}
c := &Config{
TLSConfig: TLSStruct{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
PreferServerCipherSuites: true,
},
HTTPConfig: HTTPStruct{HTTP2: true},
}
err = yaml.UnmarshalStrict(content, c)
return c, err
}
func getTLSConfig(configPath string) (*tls.Config, error) {
c, err := getConfig(configPath)
if err != nil {
return nil, err
}
return ConfigToTLSConfig(&c.TLSConfig)
}
// ConfigToTLSConfig generates the golang tls.Config from the TLSStruct config.
func ConfigToTLSConfig(c *TLSStruct) (*tls.Config, error) {
if c.TLSCertPath == "" && c.TLSKeyPath == "" && c.ClientAuth == "" && c.ClientCAs == "" {
return nil, errNoTLSConfig
}
if c.TLSCertPath == "" {
return nil, errors.New("missing cert_file")
}
if c.TLSKeyPath == "" {
return nil, errors.New("missing key_file")
}
loadCert := func() (*tls.Certificate, error) {
cert, err := tls.LoadX509KeyPair(c.TLSCertPath, c.TLSKeyPath)
if err != nil {
return nil, errors.Wrap(err, "failed to load X509KeyPair")
}
return &cert, nil
}
// Confirm that certificate and key paths are valid.
if _, err := loadCert(); err != nil {
return nil, err
}
cfg := &tls.Config{
MinVersion: (uint16)(c.MinVersion),
MaxVersion: (uint16)(c.MaxVersion),
PreferServerCipherSuites: c.PreferServerCipherSuites,
}
cfg.GetCertificate = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
return loadCert()
}
var cf []uint16
for _, c := range c.CipherSuites {
cf = append(cf, (uint16)(c))
}
if len(cf) > 0 {
cfg.CipherSuites = cf
}
var cp []tls.CurveID
for _, c := range c.CurvePreferences {
cp = append(cp, (tls.CurveID)(c))
}
if len(cp) > 0 {
cfg.CurvePreferences = cp
}
if c.ClientCAs != "" {
clientCAPool := x509.NewCertPool()
clientCAFile, err := ioutil.ReadFile(c.ClientCAs)
if err != nil {
return nil, err
}
clientCAPool.AppendCertsFromPEM(clientCAFile)
cfg.ClientCAs = clientCAPool
}
switch c.ClientAuth {
case "RequestClientCert":
cfg.ClientAuth = tls.RequestClientCert
case "RequireClientCert":
cfg.ClientAuth = tls.RequireAnyClientCert
case "VerifyClientCertIfGiven":
cfg.ClientAuth = tls.VerifyClientCertIfGiven
case "RequireAndVerifyClientCert":
cfg.ClientAuth = tls.RequireAndVerifyClientCert
case "", "NoClientCert":
cfg.ClientAuth = tls.NoClientCert
default:
return nil, errors.New("Invalid ClientAuth: " + c.ClientAuth)
}
if c.ClientCAs != "" && cfg.ClientAuth == tls.NoClientCert {
return nil, errors.New("Client CA's have been configured without a Client Auth Policy")
}
return cfg, nil
}
// Listen starts the server on the given address. If tlsConfigPath isn't empty the server connection will be started using TLS.
func Listen(server *http.Server, tlsConfigPath string, logger log.Logger) error {
if tlsConfigPath == "" {
level.Info(logger).Log("msg", "TLS is disabled.", "http2", false)
return server.ListenAndServe()
}
if err := validateUsers(tlsConfigPath); err != nil {
return err
}
// Setup basic authentication.
var handler http.Handler = http.DefaultServeMux
if server.Handler != nil {
handler = server.Handler
}
server.Handler = &userAuthRoundtrip{
tlsConfigPath: tlsConfigPath,
logger: logger,
handler: handler,
}
c, err := getConfig(tlsConfigPath)
if err != nil {
return err
}
config, err := ConfigToTLSConfig(&c.TLSConfig)
switch err {
case nil:
if !c.HTTPConfig.HTTP2 {
server.TLSNextProto = make(map[string]func(*http.Server, *tls.Conn, http.Handler))
}
// Valid TLS config.
level.Info(logger).Log("msg", "TLS is enabled.", "http2", c.HTTPConfig.HTTP2)
case errNoTLSConfig:
// No TLS config, back to plain HTTP.
level.Info(logger).Log("msg", "TLS is disabled.", "http2", false)
return server.ListenAndServe()
default:
// Invalid TLS config.
return err
}
server.TLSConfig = config
// Set the GetConfigForClient method of the HTTPS server so that the config
// and certs are reloaded on new connections.
server.TLSConfig.GetConfigForClient = func(*tls.ClientHelloInfo) (*tls.Config, error) {
return getTLSConfig(tlsConfigPath)
}
return server.ListenAndServeTLS("", "")
}
type cipher uint16
func (c *cipher) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
err := unmarshal((*string)(&s))
if err != nil {
return err
}
for _, cs := range tls.CipherSuites() {
if cs.Name == s {
*c = (cipher)(cs.ID)
return nil
}
}
return errors.New("unknown cipher: " + s)
}
func (c cipher) MarshalYAML() (interface{}, error) {
return tls.CipherSuiteName((uint16)(c)), nil
}
type curve tls.CurveID
var curves = map[string]curve{
"CurveP256": (curve)(tls.CurveP256),
"CurveP384": (curve)(tls.CurveP384),
"CurveP521": (curve)(tls.CurveP521),
"X25519": (curve)(tls.X25519),
}
func (c *curve) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
err := unmarshal((*string)(&s))
if err != nil {
return err
}
if curveid, ok := curves[s]; ok {
*c = curveid
return nil
}
return errors.New("unknown curve: " + s)
}
func (c *curve) MarshalYAML() (interface{}, error) {
for s, curveid := range curves {
if *c == curveid {
return s, nil
}
}
return fmt.Sprintf("%v", c), nil
}
type tlsVersion uint16
var tlsVersions = map[string]tlsVersion{
"TLS13": (tlsVersion)(tls.VersionTLS13),
"TLS12": (tlsVersion)(tls.VersionTLS12),
"TLS11": (tlsVersion)(tls.VersionTLS11),
"TLS10": (tlsVersion)(tls.VersionTLS10),
}
func (tv *tlsVersion) UnmarshalYAML(unmarshal func(interface{}) error) error {
var s string
err := unmarshal((*string)(&s))
if err != nil {
return err
}
if v, ok := tlsVersions[s]; ok {
*tv = v
return nil
}
return errors.New("unknown TLS version: " + s)
}
func (tv *tlsVersion) MarshalYAML() (interface{}, error) {
for s, v := range tlsVersions {
if *tv == v {
return s, nil
}
}
return fmt.Sprintf("%v", tv), nil
}

View File

@ -1,577 +0,0 @@
// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build go1.14
package https
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"regexp"
"sync"
"testing"
"time"
)
var (
port = getPort()
testlogger = &testLogger{}
ErrorMap = map[string]*regexp.Regexp{
"HTTP Response to HTTPS": regexp.MustCompile(`server gave HTTP response to HTTPS client`),
"No such file": regexp.MustCompile(`no such file`),
"Invalid argument": regexp.MustCompile(`invalid argument`),
"YAML error": regexp.MustCompile(`yaml`),
"Invalid ClientAuth": regexp.MustCompile(`invalid ClientAuth`),
"TLS handshake": regexp.MustCompile(`tls`),
"HTTP Request to HTTPS server": regexp.MustCompile(`HTTP`),
"Invalid CertPath": regexp.MustCompile(`missing cert_file`),
"Invalid KeyPath": regexp.MustCompile(`missing key_file`),
"ClientCA set without policy": regexp.MustCompile(`Client CA's have been configured without a Client Auth Policy`),
"Bad password": regexp.MustCompile(`hashedSecret too short to be a bcrypted password`),
"Unauthorized": regexp.MustCompile(`Unauthorized`),
"Forbidden": regexp.MustCompile(`Forbidden`),
"Handshake failure": regexp.MustCompile(`handshake failure`),
"Unknown cipher": regexp.MustCompile(`unknown cipher`),
"Unknown curve": regexp.MustCompile(`unknown curve`),
"Unknown TLS version": regexp.MustCompile(`unknown TLS version`),
"No HTTP2 cipher": regexp.MustCompile(`TLSConfig.CipherSuites is missing an HTTP/2-required`),
"Incompatible TLS version": regexp.MustCompile(`protocol version not supported`),
}
)
type testLogger struct{}
func (t *testLogger) Log(keyvals ...interface{}) error {
return nil
}
func getPort() string {
listener, err := net.Listen("tcp", ":0")
if err != nil {
panic(err)
}
defer listener.Close()
p := listener.Addr().(*net.TCPAddr).Port
return fmt.Sprintf(":%v", p)
}
type TestInputs struct {
Name string
Server func() *http.Server
UseNilServer bool
YAMLConfigPath string
ExpectedError *regexp.Regexp
UseTLSClient bool
ClientMaxTLSVersion uint16
CipherSuites []uint16
ActualCipher uint16
CurvePreferences []tls.CurveID
Username string
Password string
}
func TestYAMLFiles(t *testing.T) {
testTables := []*TestInputs{
{
Name: `path to config yml invalid`,
YAMLConfigPath: "somefile",
ExpectedError: ErrorMap["No such file"],
},
{
Name: `empty config yml`,
YAMLConfigPath: "testdata/tls_config_empty.yml",
ExpectedError: nil,
},
{
Name: `invalid config yml (invalid structure)`,
YAMLConfigPath: "testdata/tls_config_junk.yml",
ExpectedError: ErrorMap["YAML error"],
},
{
Name: `invalid config yml (invalid key)`,
YAMLConfigPath: "testdata/tls_config_junk_key.yml",
ExpectedError: ErrorMap["YAML error"],
},
{
Name: `invalid config yml (cert path empty)`,
YAMLConfigPath: "testdata/tls_config_noAuth_certPath_empty.bad.yml",
ExpectedError: ErrorMap["Invalid CertPath"],
},
{
Name: `invalid config yml (key path empty)`,
YAMLConfigPath: "testdata/tls_config_noAuth_keyPath_empty.bad.yml",
ExpectedError: ErrorMap["Invalid KeyPath"],
},
{
Name: `invalid config yml (cert path and key path empty)`,
YAMLConfigPath: "testdata/tls_config_noAuth_certPath_keyPath_empty.bad.yml",
ExpectedError: ErrorMap["Invalid CertPath"],
},
{
Name: `invalid config yml (cert path invalid)`,
YAMLConfigPath: "testdata/tls_config_noAuth_certPath_invalid.bad.yml",
ExpectedError: ErrorMap["No such file"],
},
{
Name: `invalid config yml (key path invalid)`,
YAMLConfigPath: "testdata/tls_config_noAuth_keyPath_invalid.bad.yml",
ExpectedError: ErrorMap["No such file"],
},
{
Name: `invalid config yml (cert path and key path invalid)`,
YAMLConfigPath: "testdata/tls_config_noAuth_certPath_keyPath_invalid.bad.yml",
ExpectedError: ErrorMap["No such file"],
},
{
Name: `invalid config yml (invalid ClientAuth)`,
YAMLConfigPath: "testdata/tls_config_noAuth.bad.yml",
ExpectedError: ErrorMap["ClientCA set without policy"],
},
{
Name: `invalid config yml (invalid ClientCAs filepath)`,
YAMLConfigPath: "testdata/tls_config_auth_clientCAs_invalid.bad.yml",
ExpectedError: ErrorMap["No such file"],
},
{
Name: `invalid config yml (invalid user list)`,
YAMLConfigPath: "testdata/tls_config_auth_user_list_invalid.bad.yml",
ExpectedError: ErrorMap["Bad password"],
},
{
Name: `invalid config yml (bad cipher)`,
YAMLConfigPath: "testdata/tls_config_noAuth_inventedCiphers.bad.yml",
ExpectedError: ErrorMap["Unknown cipher"],
},
{
Name: `invalid config yml (bad curves)`,
YAMLConfigPath: "testdata/tls_config_noAuth_inventedCurves.bad.yml",
ExpectedError: ErrorMap["Unknown curve"],
},
{
Name: `invalid config yml (bad TLS version)`,
YAMLConfigPath: "testdata/tls_config_noAuth_wrongTLSVersion.bad.yml",
ExpectedError: ErrorMap["Unknown TLS version"],
},
}
for _, testInputs := range testTables {
t.Run(testInputs.Name, testInputs.Test)
}
}
func TestServerBehaviour(t *testing.T) {
testTables := []*TestInputs{
{
Name: `empty string YAMLConfigPath and default client`,
YAMLConfigPath: "",
ExpectedError: nil,
},
{
Name: `empty string YAMLConfigPath and TLS client`,
YAMLConfigPath: "",
UseTLSClient: true,
ExpectedError: ErrorMap["HTTP Response to HTTPS"],
},
{
Name: `valid tls config yml and default client`,
YAMLConfigPath: "testdata/tls_config_noAuth.good.yml",
ExpectedError: ErrorMap["HTTP Request to HTTPS server"],
},
{
Name: `valid tls config yml and tls client`,
YAMLConfigPath: "testdata/tls_config_noAuth.good.yml",
UseTLSClient: true,
ExpectedError: nil,
},
{
Name: `valid tls config yml with TLS 1.1 client`,
YAMLConfigPath: "testdata/tls_config_noAuth.good.yml",
UseTLSClient: true,
ClientMaxTLSVersion: tls.VersionTLS11,
ExpectedError: ErrorMap["Incompatible TLS version"],
},
{
Name: `valid tls config yml with all ciphers`,
YAMLConfigPath: "testdata/tls_config_noAuth_allCiphers.good.yml",
UseTLSClient: true,
ExpectedError: nil,
},
{
Name: `valid tls config yml with some ciphers`,
YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml",
UseTLSClient: true,
CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
ExpectedError: nil,
},
{
Name: `valid tls config yml with no common cipher`,
YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml",
UseTLSClient: true,
CipherSuites: []uint16{tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
ExpectedError: ErrorMap["Handshake failure"],
},
{
Name: `valid tls config yml with multiple client ciphers`,
YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers.good.yml",
UseTLSClient: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
},
ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
ExpectedError: nil,
},
{
Name: `valid tls config yml with multiple client ciphers, client chooses cipher`,
YAMLConfigPath: "testdata/tls_config_noAuth_someCiphers_noOrder.good.yml",
UseTLSClient: true,
CipherSuites: []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
},
ActualCipher: tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
ExpectedError: nil,
},
{
Name: `valid tls config yml with all curves`,
YAMLConfigPath: "testdata/tls_config_noAuth_allCurves.good.yml",
UseTLSClient: true,
ExpectedError: nil,
},
{
Name: `valid tls config yml with some curves`,
YAMLConfigPath: "testdata/tls_config_noAuth_someCurves.good.yml",
UseTLSClient: true,
CurvePreferences: []tls.CurveID{tls.CurveP521},
ExpectedError: nil,
},
{
Name: `valid tls config yml with no common curves`,
YAMLConfigPath: "testdata/tls_config_noAuth_someCurves.good.yml",
UseTLSClient: true,
CurvePreferences: []tls.CurveID{tls.CurveP384},
ExpectedError: ErrorMap["Handshake failure"],
},
{
Name: `valid tls config yml with non-http2 ciphers`,
YAMLConfigPath: "testdata/tls_config_noAuth_noHTTP2.good.yml",
UseTLSClient: true,
ExpectedError: nil,
},
{
Name: `valid tls config yml with non-http2 ciphers but http2 enabled`,
YAMLConfigPath: "testdata/tls_config_noAuth_noHTTP2Cipher.bad.yml",
UseTLSClient: true,
ExpectedError: ErrorMap["No HTTP2 cipher"],
},
}
for _, testInputs := range testTables {
t.Run(testInputs.Name, testInputs.Test)
}
}
func TestConfigReloading(t *testing.T) {
errorChannel := make(chan error, 1)
var once sync.Once
recordConnectionError := func(err error) {
once.Do(func() {
errorChannel <- err
})
}
defer func() {
if recover() != nil {
recordConnectionError(errors.New("Panic in test function"))
}
}()
goodYAMLPath := "testdata/tls_config_noAuth.good.yml"
badYAMLPath := "testdata/tls_config_noAuth.good.blocking.yml"
server := &http.Server{
Addr: port,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World!"))
}),
}
defer func() {
server.Close()
}()
go func() {
defer func() {
if recover() != nil {
recordConnectionError(errors.New("Panic starting server"))
}
}()
err := Listen(server, badYAMLPath, testlogger)
recordConnectionError(err)
}()
client := getTLSClient()
TestClientConnection := func() error {
time.Sleep(250 * time.Millisecond)
r, err := client.Get("https://localhost" + port)
if err != nil {
return (err)
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return (err)
}
if string(body) != "Hello World!" {
return (errors.New(string(body)))
}
return (nil)
}
err := TestClientConnection()
if err == nil {
recordConnectionError(errors.New("connection accepted but should have failed"))
} else {
swapFileContents(goodYAMLPath, badYAMLPath)
defer swapFileContents(goodYAMLPath, badYAMLPath)
err = TestClientConnection()
if err != nil {
recordConnectionError(errors.New("connection failed but should have been accepted"))
} else {
recordConnectionError(nil)
}
}
err = <-errorChannel
if err != nil {
t.Errorf(" *** Failed test: %s *** Returned error: %v", "TestConfigReloading", err)
}
}
func (test *TestInputs) Test(t *testing.T) {
errorChannel := make(chan error, 1)
var once sync.Once
recordConnectionError := func(err error) {
once.Do(func() {
errorChannel <- err
})
}
defer func() {
if recover() != nil {
recordConnectionError(errors.New("Panic in test function"))
}
}()
var server *http.Server
if test.UseNilServer {
server = nil
} else {
server = &http.Server{
Addr: port,
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World!"))
}),
}
defer func() {
server.Close()
}()
}
go func() {
defer func() {
if recover() != nil {
recordConnectionError(errors.New("Panic starting server"))
}
}()
err := Listen(server, test.YAMLConfigPath, testlogger)
recordConnectionError(err)
}()
ClientConnection := func() (*http.Response, error) {
var client *http.Client
var proto string
if test.UseTLSClient {
client = getTLSClient()
t := client.Transport.(*http.Transport)
t.TLSClientConfig.MaxVersion = test.ClientMaxTLSVersion
if len(test.CipherSuites) > 0 {
t.TLSClientConfig.CipherSuites = test.CipherSuites
}
if len(test.CurvePreferences) > 0 {
t.TLSClientConfig.CurvePreferences = test.CurvePreferences
}
proto = "https"
} else {
client = http.DefaultClient
proto = "http"
}
req, err := http.NewRequest("GET", proto+"://localhost"+port, nil)
if err != nil {
t.Error(err)
}
if test.Username != "" {
req.SetBasicAuth(test.Username, test.Password)
}
return client.Do(req)
}
go func() {
time.Sleep(250 * time.Millisecond)
r, err := ClientConnection()
if err != nil {
recordConnectionError(err)
return
}
if test.ActualCipher != 0 {
if r.TLS.CipherSuite != test.ActualCipher {
recordConnectionError(
fmt.Errorf("bad cipher suite selected. Expected: %s, got: %s",
tls.CipherSuiteName(r.TLS.CipherSuite),
tls.CipherSuiteName(test.ActualCipher),
),
)
}
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
recordConnectionError(err)
return
}
if string(body) != "Hello World!" {
recordConnectionError(errors.New(string(body)))
return
}
recordConnectionError(nil)
}()
err := <-errorChannel
if test.isCorrectError(err) == false {
if test.ExpectedError == nil {
t.Logf("Expected no error, got error: %v", err)
} else {
t.Logf("Expected error matching regular expression: %v", test.ExpectedError)
t.Logf("Got: %v", err)
}
t.Fail()
}
}
func (test *TestInputs) isCorrectError(returnedError error) bool {
switch {
case returnedError == nil && test.ExpectedError == nil:
case returnedError != nil && test.ExpectedError != nil && test.ExpectedError.MatchString(returnedError.Error()):
default:
return false
}
return true
}
func getTLSClient() *http.Client {
cert, err := ioutil.ReadFile("testdata/tls-ca-chain.pem")
if err != nil {
panic("Unable to start TLS client. Check cert path")
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: func() *x509.CertPool {
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(cert)
return caCertPool
}(),
},
},
}
return client
}
func swapFileContents(file1, file2 string) error {
content1, err := ioutil.ReadFile(file1)
if err != nil {
return err
}
content2, err := ioutil.ReadFile(file2)
if err != nil {
return err
}
err = ioutil.WriteFile(file1, content2, 0644)
if err != nil {
return err
}
err = ioutil.WriteFile(file2, content1, 0644)
if err != nil {
return err
}
return nil
}
func TestUsers(t *testing.T) {
testTables := []*TestInputs{
{
Name: `without basic auth`,
YAMLConfigPath: "testdata/tls_config_users_noTLS.good.yml",
ExpectedError: ErrorMap["Unauthorized"],
},
{
Name: `with correct basic auth`,
YAMLConfigPath: "testdata/tls_config_users_noTLS.good.yml",
Username: "dave",
Password: "dave123",
ExpectedError: nil,
},
{
Name: `without basic auth and TLS`,
YAMLConfigPath: "testdata/tls_config_users.good.yml",
UseTLSClient: true,
ExpectedError: ErrorMap["Unauthorized"],
},
{
Name: `with correct basic auth and TLS`,
YAMLConfigPath: "testdata/tls_config_users.good.yml",
UseTLSClient: true,
Username: "dave",
Password: "dave123",
ExpectedError: nil,
},
{
Name: `with another correct basic auth and TLS`,
YAMLConfigPath: "testdata/tls_config_users.good.yml",
UseTLSClient: true,
Username: "carol",
Password: "carol123",
ExpectedError: nil,
},
{
Name: `with bad password and TLS`,
YAMLConfigPath: "testdata/tls_config_users.good.yml",
UseTLSClient: true,
Username: "dave",
Password: "bad",
ExpectedError: ErrorMap["Forbidden"],
},
{
Name: `with bad username and TLS`,
YAMLConfigPath: "testdata/tls_config_users.good.yml",
UseTLSClient: true,
Username: "nonexistent",
Password: "nonexistent",
ExpectedError: ErrorMap["Forbidden"],
},
}
for _, testInputs := range testTables {
t.Run(testInputs.Name, testInputs.Test)
}
}

View File

@ -1,73 +0,0 @@
// Copyright 2020 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package https
import (
"net/http"
"github.com/go-kit/kit/log"
"golang.org/x/crypto/bcrypt"
)
func validateUsers(configPath string) error {
c, err := getConfig(configPath)
if err != nil {
return err
}
for _, p := range c.Users {
_, err = bcrypt.Cost([]byte(p))
if err != nil {
return err
}
}
return nil
}
type userAuthRoundtrip struct {
tlsConfigPath string
handler http.Handler
logger log.Logger
}
func (u *userAuthRoundtrip) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c, err := getConfig(u.tlsConfigPath)
if err != nil {
u.logger.Log("msg", "Unable to parse configuration", "err", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
if len(c.Users) == 0 {
u.handler.ServeHTTP(w, r)
return
}
user, pass, ok := r.BasicAuth()
if !ok {
w.Header().Set("WWW-Authenticate", "Basic")
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
if hashedPassword, ok := c.Users[user]; ok {
if err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(pass)); err == nil {
u.handler.ServeHTTP(w, r)
return
}
}
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
}

View File

@ -1,6 +0,0 @@
# Minimal TLS configuration example. Additionally, a certificate and a key file
# are needed.
tls_server_config:
cert_file: server.crt
key_file: server.key

View File

@ -18,6 +18,7 @@ import (
"net/http" "net/http"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
"os/user"
"sort" "sort"
"github.com/prometheus/common/promlog" "github.com/prometheus/common/promlog"
@ -28,8 +29,8 @@ import (
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/common/version" "github.com/prometheus/common/version"
"github.com/prometheus/exporter-toolkit/web"
"github.com/prometheus/node_exporter/collector" "github.com/prometheus/node_exporter/collector"
"github.com/prometheus/node_exporter/https"
kingpin "gopkg.in/alecthomas/kingpin.v2" kingpin "gopkg.in/alecthomas/kingpin.v2"
) )
@ -176,6 +177,9 @@ func main() {
} }
level.Info(logger).Log("msg", "Starting node_exporter", "version", version.Info()) level.Info(logger).Log("msg", "Starting node_exporter", "version", version.Info())
level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext()) level.Info(logger).Log("msg", "Build context", "build_context", version.BuildContext())
if user, err := user.Current(); err == nil && user.Uid == "0" {
level.Warn(logger).Log("msg", "Node Exporter is running as root user. This exporter is designed to run as unpriviledged user, root is not required.")
}
http.Handle(*metricsPath, newHandler(!*disableExporterMetrics, *maxRequests, logger)) http.Handle(*metricsPath, newHandler(!*disableExporterMetrics, *maxRequests, logger))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
@ -190,7 +194,7 @@ func main() {
level.Info(logger).Log("msg", "Listening on", "address", *listenAddress) level.Info(logger).Log("msg", "Listening on", "address", *listenAddress)
server := &http.Server{Addr: *listenAddress} server := &http.Server{Addr: *listenAddress}
if err := https.Listen(server, *configFile, logger); err != nil { if err := web.ListenAndServe(server, *configFile, logger); err != nil {
level.Error(logger).Log("err", err) level.Error(logger).Log("err", err)
os.Exit(1) os.Exit(1)
} }