From 32a6d11863328ecc1c9e90b68ae148f294064aac Mon Sep 17 00:00:00 2001 From: Maximilian Praeger Date: Fri, 17 May 2019 18:40:24 +0200 Subject: [PATCH 1/3] add: support for basic ipsec metrics Signed-off-by: Maximilian Praeger --- config/config.go | 2 + ipsec/ipsec_collector.go | 81 ++++++++++++++++++++++++++++++++++++++++ ipsec/rpc.go | 29 ++++++++++++++ junos_collector.go | 5 +++ main.go | 2 + 5 files changed, 119 insertions(+) create mode 100644 ipsec/ipsec_collector.go create mode 100644 ipsec/rpc.go diff --git a/config/config.go b/config/config.go index 16745e4c..046aeef2 100644 --- a/config/config.go +++ b/config/config.go @@ -26,6 +26,7 @@ type Config struct { InterfaceDiagnostic bool `yaml:"interface_diagnostic,omitempty"` Storage bool `yaml:"storage,omitempty"` Accounting bool `yaml:"accounting,omitempty"` + Ipsec bool `yaml:"ipsec,omitempty"` } `yaml:"features,omitempty"` } @@ -61,6 +62,7 @@ func setDefaultValues(c *Config) { f.Environment = true f.Interfaces = true f.InterfaceDiagnostic = true + f.Ipsec = false f.OSPF = true f.LDP = true f.Routes = true diff --git a/ipsec/ipsec_collector.go b/ipsec/ipsec_collector.go new file mode 100644 index 00000000..a1099160 --- /dev/null +++ b/ipsec/ipsec_collector.go @@ -0,0 +1,81 @@ +package ipsec + +import ( + "fmt" + + "github.com/czerwonk/junos_exporter/collector" + "github.com/czerwonk/junos_exporter/rpc" + "github.com/prometheus/client_golang/prometheus" +) + +const prefix string = "junos_ipsec_security_associations_" + +var ( + blockState *prometheus.Desc + activeTunnels *prometheus.Desc +) + +func init() { + l := []string{"target", "description", "name"} + + blockState = prometheus.NewDesc(prefix+"state", "State of the Security Association", l, nil) + activeTunnels = prometheus.NewDesc(prefix+"active_tunnels", "Total active tunnels", l, nil) +} + +type ipsecCollector struct { +} + +// NewCollector creates a new collector +func NewCollector() collector.RPCCollector { + return &ipsecCollector{} +} + +// Describe describes the metrics +func (*ipsecCollector) Describe(ch chan<- *prometheus.Desc) { + ch <- blockState + ch <- activeTunnels +} + +// Collect collects metrics from JunOS +func (c *ipsecCollector) Collect(client *rpc.Client, ch chan<- prometheus.Metric, labelValues []string) error { + var x = IpsecRpc{} + err := client.RunCommandAndParse("show security ipsec security-associations", &x) + if err != nil { + return err + } + + ls := append(labelValues, "active tunnels", "") + ch <- prometheus.MustNewConstMetric(activeTunnels, prometheus.GaugeValue, float64(x.Information.ActiveTunnels), ls...) + + for _, block := range x.Information.SecurityAssociations { + c.collectForSecurityAssociation(block, ch, labelValues) + } + + return nil +} + +func (c *ipsecCollector) collectForSecurityAssociation(block IpsecSecurityAssociationBlock, ch chan<- prometheus.Metric, labelValues []string) { + // build SA name + var saName string + var saDesc string + for _, sa := range block.SecurityAssociations { + // saName = fmt.Sprintf("%d_%s", sa.TunnelIndex, sa.RemoteGateway) + saName = sa.RemoteGateway + saDesc = fmt.Sprintf("security association for remote gateway %s", sa.RemoteGateway) + } + lp := append(labelValues, saDesc, saName) + stateVal := stateToInt(&block.State) + ch <- prometheus.MustNewConstMetric(blockState, prometheus.GaugeValue, float64(stateVal), lp...) +} + +func stateToInt(state *string) int { + retval := 0 + + if *state == "up" { + retval = 1 + } + + fmt.Printf("state: %s -> %d\n", *state, retval) + + return retval +} diff --git a/ipsec/rpc.go b/ipsec/rpc.go new file mode 100644 index 00000000..c44376cb --- /dev/null +++ b/ipsec/rpc.go @@ -0,0 +1,29 @@ +package ipsec + +type IpsecRpc struct { + Information struct { + ActiveTunnels int `xml:"total-active-tunnels"` + SecurityAssociations []IpsecSecurityAssociationBlock `xml:"ipsec-security-associations-block"` + } `xml:"ipsec-security-associations-information"` +} + +type IpsecSecurityAssociationBlock struct { + State string `xml:"sa-block-state"` + SecurityAssociations []IpsecSecurityAssociation `xml:"ipsec-security-associations"` +} + +type IpsecSecurityAssociation struct { + Direction string `xml:"sa-direction"` + TunnelIndex int64 `xml:"sa-tunnel-index"` + Spi string `xml:"sa-spi"` + AuxSpi string `xml:"sa-aux-spi"` + RemoteGateway string `xml:"sa-remote-gateway"` + Port int `xml:"sa-port"` + MonitoringState string `xml:"sa-vpn-monitoring-state"` + Protocol string `xml:"sa-protocol"` + EspEncryptionAlgorithm string `xml:"sa-esp-encryption-algorithm"` + HmacAlgorithm string `xml:"sa-hmac-algorithm"` + HardLifetime string `xml:"sa-hard-lifetime"` + LifesizeRemaining string `xml:"sa-lifesize-remaining"` + VirtualSystem string `xml:"sa-virtual-system"` +} diff --git a/junos_collector.go b/junos_collector.go index 529b969f..182b9694 100644 --- a/junos_collector.go +++ b/junos_collector.go @@ -14,6 +14,7 @@ import ( "github.com/czerwonk/junos_exporter/firewall" "github.com/czerwonk/junos_exporter/interfacediagnostics" "github.com/czerwonk/junos_exporter/interfaces" + "github.com/czerwonk/junos_exporter/ipsec" "github.com/czerwonk/junos_exporter/isis" "github.com/czerwonk/junos_exporter/l2circuit" "github.com/czerwonk/junos_exporter/ldp" @@ -77,6 +78,10 @@ func collectors() map[string]collector.RPCCollector { m["isis"] = isis.NewCollector() } + if f.Ipsec { + m["ipsec"] = ipsec.NewCollector() + } + if f.LDP { m["ldp"] = ldp.NewCollector() } diff --git a/main.go b/main.go index 558aad4f..d7507e9d 100644 --- a/main.go +++ b/main.go @@ -49,6 +49,7 @@ var ( firewallEnabled = flag.Bool("firewall.enabled", true, "Scrape Firewall count metrics") interfacesEnabled = flag.Bool("interfaces.enabled", true, "Scrape interface metrics") interfaceDiagnosticsEnabled = flag.Bool("ifdiag.enabled", true, "Scrape optical interface diagnostic metrics") + ipsecEnabled = flag.Bool("ipsec.enabled", false, "Scrape IPSec metrics") storageEnabled = flag.Bool("storage.enabled", true, "Scrape system storage metrics") accountingEnabled = flag.Bool("accounting.enabled", false, "Scrape accounting flow metrics") alarmFilter = flag.String("alarms.filter", "", "Regex to filter for alerts to ignore") @@ -175,6 +176,7 @@ func loadConfigFromFlags() *config.Config { f.Firewall = *firewallEnabled f.Interfaces = *interfacesEnabled f.InterfaceDiagnostic = *interfaceDiagnosticsEnabled + f.Ipsec = *ipsecEnabled f.ISIS = *isisEnabled f.NAT = *natEnabled f.OSPF = *ospfEnabled From c25606677a34d316f9527c0e3c35ebe8958bb4ea Mon Sep 17 00:00:00 2001 From: Maximilian Praeger Date: Fri, 17 May 2019 19:17:59 +0200 Subject: [PATCH 2/3] change: comments for types and remove old code Signed-off-by: Maximilian Praeger --- ipsec/ipsec_collector.go | 1 - ipsec/rpc.go | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ipsec/ipsec_collector.go b/ipsec/ipsec_collector.go index a1099160..75121b64 100644 --- a/ipsec/ipsec_collector.go +++ b/ipsec/ipsec_collector.go @@ -59,7 +59,6 @@ func (c *ipsecCollector) collectForSecurityAssociation(block IpsecSecurityAssoci var saName string var saDesc string for _, sa := range block.SecurityAssociations { - // saName = fmt.Sprintf("%d_%s", sa.TunnelIndex, sa.RemoteGateway) saName = sa.RemoteGateway saDesc = fmt.Sprintf("security association for remote gateway %s", sa.RemoteGateway) } diff --git a/ipsec/rpc.go b/ipsec/rpc.go index c44376cb..9fe42fcf 100644 --- a/ipsec/rpc.go +++ b/ipsec/rpc.go @@ -1,5 +1,6 @@ package ipsec +// IpsecRpc is the root element for xml unmarshalling type IpsecRpc struct { Information struct { ActiveTunnels int `xml:"total-active-tunnels"` @@ -7,11 +8,13 @@ type IpsecRpc struct { } `xml:"ipsec-security-associations-information"` } +// IpsecSecurityAssociationBlock is used for xml unmarshalling type IpsecSecurityAssociationBlock struct { State string `xml:"sa-block-state"` SecurityAssociations []IpsecSecurityAssociation `xml:"ipsec-security-associations"` } +// IpsecSecurityAssociation is used for xml unmarshalling type IpsecSecurityAssociation struct { Direction string `xml:"sa-direction"` TunnelIndex int64 `xml:"sa-tunnel-index"` From 425a20225c10396375a1f9bf6571b2af2322c00e Mon Sep 17 00:00:00 2001 From: Maximilian Praeger Date: Fri, 17 May 2019 19:47:06 +0200 Subject: [PATCH 3/3] remove: debug output Signed-off-by: Maximilian Praeger --- ipsec/ipsec_collector.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/ipsec/ipsec_collector.go b/ipsec/ipsec_collector.go index 75121b64..f149d59c 100644 --- a/ipsec/ipsec_collector.go +++ b/ipsec/ipsec_collector.go @@ -74,7 +74,5 @@ func stateToInt(state *string) int { retval = 1 } - fmt.Printf("state: %s -> %d\n", *state, retval) - return retval }