mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-25 01:13:40 +01:00
Merge pull request #37 from Exagone313/certificate-expiration
Add certificate expiration support
This commit is contained in:
commit
d1f24dbea4
15
README.md
15
README.md
@ -161,13 +161,14 @@ Here are some examples of conditions you can use:
|
|||||||
|
|
||||||
#### Placeholders
|
#### Placeholders
|
||||||
|
|
||||||
| Placeholder | Description | Example of resolved value |
|
| Placeholder | Description | Example of resolved value |
|
||||||
|:----------------------- |:------------------------------------------------------- |:------------------------- |
|
|:-------------------------- |:--------------------------------------------------------------- |:------------------------- |
|
||||||
| `[STATUS]` | Resolves into the HTTP status of the request | 404
|
| `[STATUS]` | Resolves into the HTTP status of the request | 404
|
||||||
| `[RESPONSE_TIME]` | Resolves into the response time the request took, in ms | 10
|
| `[RESPONSE_TIME]` | Resolves into the response time the request took, in ms | 10
|
||||||
| `[IP]` | Resolves into the IP of the target host | 192.168.0.232
|
| `[IP]` | Resolves into the IP of the target host | 192.168.0.232
|
||||||
| `[BODY]` | Resolves into the response body. Supports JSONPath. | `{"name":"john.doe"}`
|
| `[BODY]` | Resolves into the response body. Supports JSONPath. | `{"name":"john.doe"}`
|
||||||
| `[CONNECTED]` | Resolves into whether a connection could be established | `true`
|
| `[CONNECTED]` | Resolves into whether a connection could be established | `true`
|
||||||
|
| `[CERTIFICATE_EXPIRATION]` | Resolves into the duration before certificate expiration, in ms | 4461677039, 0 (if not using HTTPS)
|
||||||
|
|
||||||
|
|
||||||
#### Functions
|
#### Functions
|
||||||
|
@ -35,6 +35,11 @@ const (
|
|||||||
// Values that could replace the placeholder: true, false
|
// Values that could replace the placeholder: true, false
|
||||||
ConnectedPlaceHolder = "[CONNECTED]"
|
ConnectedPlaceHolder = "[CONNECTED]"
|
||||||
|
|
||||||
|
// CertificateExpirationPlaceholder is a placeholder for the duration before certificate expiration, in milliseconds.
|
||||||
|
//
|
||||||
|
// Values that could replace the placeholder: 4461677039 (~52 days)
|
||||||
|
CertificateExpirationPlaceholder = "[CERTIFICATE_EXPIRATION]"
|
||||||
|
|
||||||
// LengthFunctionPrefix is the prefix for the length function
|
// LengthFunctionPrefix is the prefix for the length function
|
||||||
LengthFunctionPrefix = "len("
|
LengthFunctionPrefix = "len("
|
||||||
|
|
||||||
@ -142,6 +147,8 @@ func sanitizeAndResolve(list []string, result *Result) []string {
|
|||||||
element = body
|
element = body
|
||||||
case ConnectedPlaceHolder:
|
case ConnectedPlaceHolder:
|
||||||
element = strconv.FormatBool(result.Connected)
|
element = strconv.FormatBool(result.Connected)
|
||||||
|
case CertificateExpirationPlaceholder:
|
||||||
|
element = strconv.FormatInt(int64(result.CertificateExpiration.Milliseconds()), 10)
|
||||||
default:
|
default:
|
||||||
// if contains the BodyPlaceHolder, then evaluate json path
|
// if contains the BodyPlaceHolder, then evaluate json path
|
||||||
if strings.Contains(element, BodyPlaceHolder) {
|
if strings.Contains(element, BodyPlaceHolder) {
|
||||||
@ -174,11 +181,11 @@ func sanitizeAndResolve(list []string, result *Result) []string {
|
|||||||
return sanitizedList
|
return sanitizedList
|
||||||
}
|
}
|
||||||
|
|
||||||
func sanitizeAndResolveNumerical(list []string, result *Result) []int {
|
func sanitizeAndResolveNumerical(list []string, result *Result) []int64 {
|
||||||
var sanitizedNumbers []int
|
var sanitizedNumbers []int64
|
||||||
sanitizedList := sanitizeAndResolve(list, result)
|
sanitizedList := sanitizeAndResolve(list, result)
|
||||||
for _, element := range sanitizedList {
|
for _, element := range sanitizedList {
|
||||||
if number, err := strconv.Atoi(element); err != nil {
|
if number, err := strconv.ParseInt(element, 10, 64); err != nil {
|
||||||
// Default to 0 if the string couldn't be converted to an integer
|
// Default to 0 if the string couldn't be converted to an integer
|
||||||
sanitizedNumbers = append(sanitizedNumbers, 0)
|
sanitizedNumbers = append(sanitizedNumbers, 0)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -309,3 +310,32 @@ func TestCondition_evaluateWithConnectedFailure(t *testing.T) {
|
|||||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCondition_evaluateWithUnsetCertificateExpiration(t *testing.T) {
|
||||||
|
condition := Condition("[CERTIFICATE_EXPIRATION] == 0")
|
||||||
|
result := &Result{}
|
||||||
|
condition.evaluate(result)
|
||||||
|
if !result.ConditionResults[0].Success {
|
||||||
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCondition_evaluateWithCertificateExpirationGreaterThan(t *testing.T) {
|
||||||
|
acceptable := (time.Hour * 24 * 28).Milliseconds()
|
||||||
|
condition := Condition("[CERTIFICATE_EXPIRATION] > " + strconv.FormatInt(acceptable, 10))
|
||||||
|
result := &Result{CertificateExpiration: time.Hour * 24 * 60}
|
||||||
|
condition.evaluate(result)
|
||||||
|
if !result.ConditionResults[0].Success {
|
||||||
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCondition_evaluateWithCertificateExpirationGreaterThanFailure(t *testing.T) {
|
||||||
|
acceptable := (time.Hour * 24 * 28).Milliseconds()
|
||||||
|
condition := Condition("[CERTIFICATE_EXPIRATION] > " + strconv.FormatInt(acceptable, 10))
|
||||||
|
result := &Result{CertificateExpiration: time.Hour * 24 * 14}
|
||||||
|
condition.evaluate(result)
|
||||||
|
if result.ConditionResults[0].Success {
|
||||||
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -169,6 +169,10 @@ func (service *Service) call(result *Result) {
|
|||||||
result.Errors = append(result.Errors, err.Error())
|
result.Errors = append(result.Errors, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if response.TLS != nil {
|
||||||
|
certificate := response.TLS.PeerCertificates[0]
|
||||||
|
result.CertificateExpiration = certificate.NotAfter.Sub(time.Now())
|
||||||
|
}
|
||||||
result.HTTPStatus = response.StatusCode
|
result.HTTPStatus = response.StatusCode
|
||||||
result.Connected = response.StatusCode > 0
|
result.Connected = response.StatusCode > 0
|
||||||
result.Body, err = ioutil.ReadAll(response.Body)
|
result.Body, err = ioutil.ReadAll(response.Body)
|
||||||
|
@ -45,6 +45,9 @@ type Result struct {
|
|||||||
|
|
||||||
// Timestamp when the request was sent
|
// Timestamp when the request was sent
|
||||||
Timestamp time.Time `json:"timestamp"`
|
Timestamp time.Time `json:"timestamp"`
|
||||||
|
|
||||||
|
// CertificateExpiration is the duration before the certificate expires
|
||||||
|
CertificateExpiration time.Duration `json:"certificate-expiration,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConditionResult result of a Condition
|
// ConditionResult result of a Condition
|
||||||
|
Loading…
Reference in New Issue
Block a user