File: driver_webhook.go

package info (click to toggle)
incus 6.0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,392 kB
  • sloc: sh: 16,313; ansic: 3,121; python: 457; makefile: 337; ruby: 51; sql: 50; lisp: 6
file content (122 lines) | stat: -rw-r--r-- 2,660 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package logging

import (
	"bytes"
	"context"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"net/http"
	"time"

	"github.com/lxc/incus/v6/internal/server/state"
	"github.com/lxc/incus/v6/shared/api"
	incustls "github.com/lxc/incus/v6/shared/tls"
)

// WebhookLogger represents a webhook logger.
type WebhookLogger struct {
	common

	client   *http.Client
	address  string
	username string
	password string
	retry    int
}

// NewWebhookLogger instantiates a new webhook logger.
func NewWebhookLogger(s *state.State, name string) (*WebhookLogger, error) {
	address, username, password, caCertificate, retry := s.GlobalConfig.LoggingConfigForWebhook(name)

	client := &http.Client{}

	// Set defaults.
	if retry == 0 {
		retry = 3
	}

	// Setup the server for self-signed certirficates.
	if caCertificate != "" {
		// Prepare the TLS config.
		tlsConfig := &tls.Config{
			MinVersion: tls.VersionTLS13,
		}

		// Parse the provided certificate.
		certBlock, _ := pem.Decode([]byte(caCertificate))
		if certBlock == nil {
			return nil, errors.New("Invalid remote certificate")
		}

		serverCert, err := x509.ParseCertificate(certBlock.Bytes)
		if err != nil {
			return nil, fmt.Errorf("Invalid remote certificate: %w", err)
		}

		// Add the certificate to the TLS config.
		incustls.TLSConfigWithTrustedCert(tlsConfig, serverCert)

		// Configure the HTTP client with our TLS config.
		client.Transport = &http.Transport{TLSClientConfig: tlsConfig}
	}

	return &WebhookLogger{
		common:   newCommonLogger(name, s.GlobalConfig),
		client:   client,
		address:  address,
		username: username,
		password: password,
		retry:    retry,
	}, nil
}

// HandleEvent handles the event received from the internal event listener.
func (c *WebhookLogger) HandleEvent(event api.Event) {
	// JSON data.
	data, err := json.Marshal(event)
	if err != nil {
		return
	}

	// Prepare the request.
	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, c.address, bytes.NewReader(data))
	if err != nil {
		return
	}

	req.Header.Set("Content-Type", "application/json")

	for range c.retry {
		resp, err := c.client.Do(req)
		if err != nil {
			// Wait 10s and try again.
			time.Sleep(10 * time.Second)

			continue
		}

		_ = resp.Body.Close()
	}
}

// Start starts the webhook logger.
func (c *WebhookLogger) Start() error {
	return nil
}

// Stop cleans up the webhook logger.
func (c *WebhookLogger) Stop() {
}

// Validate checks whether the logger configuration is correct.
func (c *WebhookLogger) Validate() error {
	if c.address == "" {
		return fmt.Errorf("%s: Address cannot be empty", c.name)
	}

	return nil
}