Skip to content

Commit 62be326

Browse files
committed
Install CA in clients
1 parent ed9ea53 commit 62be326

File tree

3 files changed

+85
-7
lines changed

3 files changed

+85
-7
lines changed

internal/certs/pool.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
package certs
6+
7+
import (
8+
"crypto/x509"
9+
"encoding/pem"
10+
"fmt"
11+
"io/ioutil"
12+
)
13+
14+
func SystemPoolWithCACertificate(path string) (*x509.CertPool, error) {
15+
d, err := ioutil.ReadFile(path)
16+
if err != nil {
17+
return nil, err
18+
}
19+
20+
cert, _ := pem.Decode(d)
21+
if cert == nil || cert.Type != "CERTIFICATE" {
22+
return nil, fmt.Errorf("no certificate found in %q", path)
23+
}
24+
25+
ca, err := x509.ParseCertificate(cert.Bytes)
26+
if err != nil {
27+
return nil, fmt.Errorf("parsing certificate found in %q: %w", path, err)
28+
}
29+
30+
pool, err := x509.SystemCertPool()
31+
if err != nil {
32+
return nil, fmt.Errorf("initializing root certificate pool: %w", path, err)
33+
}
34+
pool.AddCert(ca)
35+
36+
return pool, nil
37+
}

internal/elasticsearch/client.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package elasticsearch
66

77
import (
88
"crypto/tls"
9+
"fmt"
910
"net/http"
1011
"os"
1112

@@ -14,6 +15,7 @@ import (
1415
"github.com/elastic/go-elasticsearch/v7"
1516
"github.com/elastic/go-elasticsearch/v7/esapi"
1617

18+
"github.com/elastic/elastic-package/internal/certs"
1719
"github.com/elastic/elastic-package/internal/stack"
1820
)
1921

@@ -32,16 +34,20 @@ type clientOptions struct {
3234
username string
3335
password string
3436

37+
// certificateAuthority is the certificate to validate the server certificate.
38+
certificateAuthority string
39+
3540
// skipTLSVerify disables TLS validation.
3641
skipTLSVerify bool
3742
}
3843

3944
// defaultOptionsFromEnv returns clientOptions initialized with values from environmet variables.
4045
func defaultOptionsFromEnv() clientOptions {
4146
return clientOptions{
42-
address: os.Getenv(stack.ElasticsearchHostEnv),
43-
username: os.Getenv(stack.ElasticsearchUsernameEnv),
44-
password: os.Getenv(stack.ElasticsearchPasswordEnv),
47+
address: os.Getenv(stack.ElasticsearchHostEnv),
48+
username: os.Getenv(stack.ElasticsearchUsernameEnv),
49+
password: os.Getenv(stack.ElasticsearchPasswordEnv),
50+
certificateAuthority: os.Getenv(stack.CACertificateEnv),
4551
}
4652
}
4753

@@ -54,6 +60,13 @@ func OptionWithAddress(address string) ClientOption {
5460
}
5561
}
5662

63+
// OptionWithCertificateAuthority sets the certificate authority to be used by the client.
64+
func OptionWithCertificateAuthority(certificateAuthority string) ClientOption {
65+
return func(opts *clientOptions) {
66+
opts.certificateAuthority = certificateAuthority
67+
}
68+
}
69+
5770
// OptionWithSkipTLSVerify disables TLS validation.
5871
func OptionWithSkipTLSVerify() ClientOption {
5972
return func(opts *clientOptions) {
@@ -81,6 +94,14 @@ func Client(customOptions ...ClientOption) (*elasticsearch.Client, error) {
8194
config.Transport = &http.Transport{
8295
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
8396
}
97+
} else if options.certificateAuthority != "" {
98+
rootCAs, err := certs.SystemPoolWithCACertificate(options.certificateAuthority)
99+
if err != nil {
100+
return nil, fmt.Errorf("reading CA certificate: %w", err)
101+
}
102+
config.Transport = &http.Transport{
103+
TLSClientConfig: &tls.Config{RootCAs: rootCAs},
104+
}
84105
}
85106

86107
client, err := elasticsearch.NewClient(config)

internal/kibana/client.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ package kibana
77
import (
88
"bytes"
99
"crypto/tls"
10+
"fmt"
1011
"io"
1112
"net/http"
1213
"net/url"
1314
"os"
1415

1516
"github.com/pkg/errors"
1617

18+
"github.com/elastic/elastic-package/internal/certs"
1719
"github.com/elastic/elastic-package/internal/install"
1820
"github.com/elastic/elastic-package/internal/logger"
1921
"github.com/elastic/elastic-package/internal/stack"
@@ -25,7 +27,8 @@ type Client struct {
2527
username string
2628
password string
2729

28-
tlSkipVerify bool
30+
certificateAuthority string
31+
tlSkipVerify bool
2932
}
3033

3134
// ClientOption is functional option modifying Kibana client.
@@ -40,11 +43,13 @@ func NewClient(opts ...ClientOption) (*Client, error) {
4043

4144
username := os.Getenv(stack.ElasticsearchUsernameEnv)
4245
password := os.Getenv(stack.ElasticsearchPasswordEnv)
46+
certificateAuthority := os.Getenv(stack.CACertificateEnv)
4347

4448
c := &Client{
45-
host: host,
46-
username: username,
47-
password: password,
49+
host: host,
50+
username: username,
51+
password: password,
52+
certificateAuthority: certificateAuthority,
4853
}
4954

5055
for _, opt := range opts {
@@ -60,6 +65,13 @@ func TLSSkipVerify() ClientOption {
6065
}
6166
}
6267

68+
// CertificateAuthority sets the certificate authority to be used by the client.
69+
func CertificateAuthority(certificateAuthority string) ClientOption {
70+
return func(c *Client) {
71+
c.certificateAuthority = certificateAuthority
72+
}
73+
}
74+
6375
func (c *Client) get(resourcePath string) (int, []byte, error) {
6476
return c.sendRequest(http.MethodGet, resourcePath, nil)
6577
}
@@ -106,6 +118,14 @@ func (c *Client) sendRequest(method, resourcePath string, body []byte) (int, []b
106118
client.Transport = &http.Transport{
107119
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
108120
}
121+
} else if c.certificateAuthority != "" {
122+
rootCAs, err := certs.SystemPoolWithCACertificate(c.certificateAuthority)
123+
if err != nil {
124+
return 0, nil, fmt.Errorf("reading CA certificate: %w", err)
125+
}
126+
client.Transport = &http.Transport{
127+
TLSClientConfig: &tls.Config{RootCAs: rootCAs},
128+
}
109129
}
110130

111131
resp, err := client.Do(req)

0 commit comments

Comments
 (0)