Skip to content

Commit aae76ec

Browse files
committed
sslstatus: ssl check with native go
1 parent be0a92d commit aae76ec

File tree

2 files changed

+59
-107
lines changed

2 files changed

+59
-107
lines changed

services/sslstatus/sslcheck.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package sslstatus
2+
3+
import (
4+
"crypto/tls"
5+
"fmt"
6+
"strings"
7+
"time"
8+
)
9+
10+
func checkSSLExpiry(domain string) string {
11+
conn, err := tls.Dial("tcp", domain+":443", &tls.Config{})
12+
if err != nil {
13+
return fmt.Sprintf("error: %s - %v\n", strings.TrimPrefix(domain, "*."), err)
14+
}
15+
16+
defer conn.Close()
17+
18+
cleanDomain := strings.TrimPrefix(domain, "*.")
19+
20+
certs := conn.ConnectionState().PeerCertificates
21+
if len(certs) > 0 {
22+
cert := certs[0]
23+
daysLeft := int(time.Until(cert.NotAfter).Hours() / 24)
24+
25+
status := "Info"
26+
if daysLeft <= 30 {
27+
status = "Warning"
28+
} else if daysLeft <= 15 {
29+
status = "Danger"
30+
} else if daysLeft <= 7 {
31+
status = "Critical"
32+
}
33+
34+
return fmt.Sprintf("%s: %s will expire in %d days (%s)\n",
35+
status,
36+
cleanDomain,
37+
daysLeft,
38+
cert.NotAfter.Format(time.RFC1123))
39+
}
40+
41+
return fmt.Sprintf("failed to perform a TLS handshake for the domain: %s \n", cleanDomain)
42+
}
43+
44+
func checkSSLExpiryMulti(domains []string) string {
45+
var sb strings.Builder
46+
47+
for _, domain := range domains {
48+
sb.WriteString(checkSSLExpiry(domain))
49+
}
50+
return sb.String()
51+
}

services/sslstatus/sslstatus.go

Lines changed: 8 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
package sslstatus
22

33
import (
4-
"bytes"
5-
"encoding/json"
6-
"fmt"
74
"log"
8-
"net"
9-
"net/url"
105
"strings"
116
"time"
127

138
"github.com/telkomdev/tob"
149
"github.com/telkomdev/tob/config"
15-
"github.com/telkomdev/tob/data"
16-
"github.com/telkomdev/tob/httpx"
1710
"github.com/telkomdev/tob/util"
1811
)
1912

@@ -32,12 +25,6 @@ type SSLStatus struct {
3225
notificatorConfig config.Config
3326
}
3427

35-
type target struct {
36-
Success bool `json:"success"`
37-
Message string `json:"message"`
38-
Data string `json:"data"`
39-
}
40-
4128
var SEVERITIES = []string{"Warning", "Danger", "Critical"}
4229

4330
// NewSSLStatus SSLStatus's constructor
@@ -59,112 +46,26 @@ func (d *SSLStatus) Name() string {
5946
return "sslstatus"
6047
}
6148

62-
// Resolve hostname to IPv4 address
63-
func (d *SSLStatus) resolveIPv4() string {
64-
ipv4 := "N/A"
65-
66-
hostUrl, err := url.Parse(d.url)
67-
if err != nil {
68-
if d.verbose {
69-
d.logger.Println(err)
70-
}
71-
return ipv4
72-
}
73-
hostname := hostUrl.Hostname()
74-
75-
ips, err := net.LookupIP(hostname)
76-
if err != nil {
77-
if d.verbose {
78-
d.logger.Println(err)
79-
}
80-
return ipv4
81-
}
82-
83-
for _, ip := range ips {
84-
if ip.To4() != nil {
85-
ipv4 = ip.String()
86-
break
87-
}
88-
}
89-
90-
return ipv4
91-
}
92-
9349
// Ping will try to ping the service
9450
func (d *SSLStatus) Ping() []byte {
95-
shellFilePathStr, ok := d.configs["shellFile"].(string)
51+
domains, ok := d.configs["domains"].([]interface{})
9652
if !ok {
9753
if d.verbose {
98-
d.logger.Println("shellFilePathStr is not valid")
99-
}
100-
return []byte("NOT_OK")
101-
}
102-
103-
if d.verbose {
104-
d.logger.Printf("tob-http-agent check %s SSL Status\n", shellFilePathStr)
105-
}
106-
107-
fileSystemPayload := data.FileSystem{
108-
Path: shellFilePathStr,
109-
}
110-
111-
payloadJSON, err := json.Marshal(fileSystemPayload)
112-
if err != nil {
113-
if d.verbose {
114-
d.logger.Println(err)
54+
d.logger.Println("domains is not in the SSL_status config")
11555
}
11656
return []byte("NOT_OK")
11757
}
11858

119-
headers := make(map[string]string)
120-
headers["Content-Type"] = "application/json"
59+
var domianStrs []string
12160

122-
resp, err := httpx.HTTPPost(fmt.Sprintf("%s/check-ssl", d.url), bytes.NewBuffer(payloadJSON), headers, 120)
123-
if err != nil {
124-
if d.verbose {
125-
d.logger.Println(err)
126-
}
127-
return []byte("NOT_OK")
128-
}
129-
130-
statusOK := resp.StatusCode >= 200 && resp.StatusCode < 300
131-
if !statusOK {
132-
if d.verbose {
133-
d.logger.Printf("SSLStatus Ping status: %d\n", resp.StatusCode)
134-
}
135-
136-
return []byte("NOT_OK")
137-
}
138-
139-
if d.verbose {
140-
d.logger.Printf("SSLStatus Ping status: %d\n", resp.StatusCode)
141-
}
142-
143-
defer func() { resp.Body.Close() }()
144-
145-
var target target
146-
147-
err = json.NewDecoder(resp.Body).Decode(&target)
148-
if err != nil {
149-
if d.verbose {
150-
d.logger.Println(err)
61+
for _, domain := range domains {
62+
domainStr, ok := domain.(string)
63+
if ok {
64+
domianStrs = append(domianStrs, domainStr)
15165
}
152-
153-
return []byte("NOT_OK")
15466
}
15567

156-
if d.verbose {
157-
d.logger.Println(target)
158-
}
159-
160-
sslStatusData := target.Data
161-
162-
ipv4 := d.resolveIPv4()
163-
164-
if d.verbose {
165-
d.logger.Println("IP :", ipv4)
166-
d.logger.Println("sslStatusData: ", sslStatusData)
167-
}
68+
sslStatusData := checkSSLExpiryMulti(domianStrs)
16869

16970
d.SetMessage(sslStatusData)
17071

0 commit comments

Comments
 (0)