1package tlsconfig
2
3import (
4	"crypto/tls"
5	"crypto/x509"
6	"errors"
7	"fmt"
8	"io/ioutil"
9
10	"zabbix.com/pkg/uri"
11)
12
13type Details struct {
14	SessionName string
15	TlsConnect  string
16	TlsCaFile   string
17	TlsCertFile string
18	TlsKeyFile  string
19	RawUri      string
20}
21
22func CreateConfig(details Details, skipVerify bool) (*tls.Config, error) {
23	rootCertPool := x509.NewCertPool()
24	pem, err := ioutil.ReadFile(details.TlsCaFile)
25	if err != nil {
26		return nil, err
27	}
28
29	if ok := rootCertPool.AppendCertsFromPEM(pem); !ok {
30		return nil, errors.New("Failed to append PEM.")
31	}
32
33	clientCerts := make([]tls.Certificate, 0, 1)
34	certs, err := tls.LoadX509KeyPair(details.TlsCertFile, details.TlsKeyFile)
35	if err != nil {
36		return nil, err
37	}
38
39	clientCerts = append(clientCerts, certs)
40
41	if skipVerify {
42		return &tls.Config{RootCAs: rootCertPool, Certificates: clientCerts, InsecureSkipVerify: skipVerify}, nil
43	}
44
45	url, err := uri.New(details.RawUri, nil)
46	if err != nil {
47		return nil, err
48	}
49
50	return &tls.Config{
51		RootCAs: rootCertPool, Certificates: clientCerts, InsecureSkipVerify: skipVerify, ServerName: url.Host(),
52	}, nil
53}
54
55func CreateDetails(session, dbConnect, caFile, certFile, keyFile, uri string) (Details, error) {
56	if dbConnect != "" && dbConnect != "required" {
57		if err := validateSetTLSFiles(caFile, certFile, keyFile); err != nil {
58			return Details{}, fmt.Errorf("%s uri %s, with session %s", err.Error(), uri, session)
59		}
60	} else {
61		if err := validateUnsetTLSFiles(caFile, certFile, keyFile); err != nil {
62			return Details{}, fmt.Errorf("%s uri %s, with session %s", err.Error(), uri, session)
63		}
64	}
65
66	return Details{session, dbConnect, caFile, certFile, keyFile, uri}, nil
67}
68
69func validateSetTLSFiles(caFile, certFile, keyFile string) error {
70	if caFile == "" {
71		return errors.New("missing TLS CA file for database")
72	}
73
74	if certFile == "" {
75		return errors.New("missing TLS certificate file for database")
76	}
77
78	if keyFile == "" {
79		return errors.New("missing TLS key file for database")
80	}
81
82	return nil
83}
84
85func validateUnsetTLSFiles(caFile, certFile, keyFile string) error {
86	if caFile != "" {
87		return errors.New(
88			"TLS CA file configuration parameter set without certificates being used for database")
89	}
90
91	if certFile != "" {
92		return errors.New(
93			"TLS certificate file configuration parameter set without certificates being used for database")
94	}
95
96	if keyFile != "" {
97		return errors.New(
98			"TLS key file configuration parameter set without certificates being used for database")
99	}
100
101	return nil
102}
103