Skip to content

Commit 2ae92fd

Browse files
authored
Merge pull request #37 from rickardgranberg/tls_config
Implement support for provider root CA configuration
2 parents e990997 + bb8378c commit 2ae92fd

File tree

8 files changed

+452
-10
lines changed

8 files changed

+452
-10
lines changed

docs/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ For background information please review the [Technical Preview](https://github.
1111
provider "jetstream" {
1212
servers = "connect.ngs.global:4222"
1313
credentials = "/home/you/ngs_stream_admin.creds"
14+
tls = {
15+
ca_file_data = "<Root CA PEM data>"
16+
}
1417
}
1518
1619
resource "jetstream_stream" "ORDERS" {
@@ -34,6 +37,8 @@ resource "jetstream_consumer" "ORDERS_NEW" {
3437
* `servers` - The list of servers to connect to in a comma seperated list
3538
* `credentials` - (optional) Fully Qualified Path to a file holding NATS credentials.
3639
* `credential_data` - (optional) The NATS credentials as a string, intended to use with data providers.
40+
* `tls.ca_file` - (optional) Fully Qualified Path to a file containing Root CA (PEM format). Use when the server has certs signed by an unknown authority.
41+
* `tls.ca_file_data` - (optional) The Root CA PEM as a string, intended to use with data providers. Use when the server has certs signed by an unknown authority.
3742

3843
## Resources
3944

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,7 @@ require (
1111
github.com/nats-io/nats.go v1.12.0
1212
github.com/xeipuuv/gojsonschema v1.2.0
1313
github.com/zclconf/go-cty v1.8.4 // indirect
14-
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
14+
golang.org/x/mod v0.5.1 // indirect
15+
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
16+
golang.org/x/tools v0.1.7 // indirect
1517
)

go.sum

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
353353
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
354354
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
355355
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
356+
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
356357
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
357358
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
358359
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
@@ -412,8 +413,10 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
412413
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
413414
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
414415
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
415-
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
416416
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
417+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
418+
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
419+
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
417420
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
418421
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
419422
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -447,8 +450,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
447450
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
448451
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
449452
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
450-
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
451-
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
453+
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
454+
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
452455
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
453456
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
454457
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -465,6 +468,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
465468
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
466469
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
467470
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
471+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
468472
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
469473
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
470474
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -501,8 +505,10 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
501505
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
502506
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
503507
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
504-
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
505508
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
509+
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
510+
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
511+
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
506512
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
507513
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
508514
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -558,8 +564,9 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc
558564
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
559565
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
560566
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
561-
golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb h1:KVWk3RW1AZlxWum4tYqegLgwJHb5oouozcGM8HfNQaw=
562567
golang.org/x/tools v0.0.0-20201028111035-eafbe7b904eb/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
568+
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
569+
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
563570
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
564571
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
565572
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

jetstream/provider.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@ func Provider() terraform.ResourceProvider {
3232
Optional: true,
3333
Description: "The contents of the NATS 2.0 Credentials file to use",
3434
},
35+
"tls": {
36+
Type: schema.TypeSet,
37+
MaxItems: 1,
38+
Optional: true,
39+
Elem: &schema.Resource{
40+
Schema: map[string]*schema.Schema{
41+
"ca_file": {
42+
Type: schema.TypeString,
43+
Optional: true,
44+
Description: "Path to the server root CA file (in PEM format). Needed when the NATS server has TLS enabled with an unknown root CA",
45+
},
46+
"ca_file_data": {
47+
Type: schema.TypeString,
48+
Optional: true,
49+
Description: "The root CA (file) content, in PEM format. Needed when the NATS server has TLS enabled with an unknown root CA",
50+
},
51+
},
52+
},
53+
},
3554
},
3655

3756
ResourcesMap: map[string]*schema.Resource{

jetstream/provider_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package jetstream
22

33
import (
44
"io/ioutil"
5+
"log"
56
"testing"
67
"time"
78

@@ -12,12 +13,22 @@ import (
1213

1314
var testJsProviders map[string]terraform.ResourceProvider
1415
var testJsProvider *schema.Provider
16+
var caPEM string
17+
var certPEM string
18+
var keyPEM string
1519

1620
func init() {
1721
testJsProvider = Provider().(*schema.Provider)
1822
testJsProviders = map[string]terraform.ResourceProvider{
1923
"jetstream": testJsProvider,
2024
}
25+
26+
var err error
27+
caPEM, certPEM, keyPEM, err = generateCerts()
28+
29+
if err != nil {
30+
log.Fatal(err)
31+
}
2132
}
2233

2334
func checkErr(t *testing.T, err error, format string, a ...interface{}) {
@@ -50,3 +61,31 @@ func createJSServer(t *testing.T) (srv *server.Server) {
5061

5162
return srv
5263
}
64+
65+
func createJSTLSServer(t *testing.T) (srv *server.Server) {
66+
t.Helper()
67+
68+
dir, err := ioutil.TempDir("", "")
69+
checkErr(t, err, "could not create temporary js store: %v", err)
70+
71+
tlsConfig, err := newTLSConfig(caPEM, certPEM, keyPEM)
72+
73+
checkErr(t, err, "could not create TLS Config: %v", err)
74+
75+
srv, err = server.NewServer(&server.Options{
76+
Port: -1,
77+
Host: "localhost",
78+
StoreDir: dir,
79+
JetStream: true,
80+
TLS: true,
81+
TLSConfig: tlsConfig,
82+
})
83+
checkErr(t, err, "could not start js server: %v", err)
84+
85+
go srv.Start()
86+
if !srv.ReadyForConnections(10 * time.Second) {
87+
t.Errorf("nats server did not start")
88+
}
89+
90+
return srv
91+
}

jetstream/provider_tls_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package jetstream
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
8+
"github.com/nats-io/jsm.go"
9+
"github.com/nats-io/nats.go"
10+
)
11+
12+
const testTLSConfig_file_data = `
13+
provider "jetstream" {
14+
servers = "%s"
15+
tls {
16+
ca_file_data = <<EOT
17+
%s
18+
EOT
19+
}
20+
}
21+
22+
resource "jetstream_stream" "test" {
23+
name = "TEST"
24+
subjects = ["TEST.*"]
25+
}
26+
`
27+
28+
const testTLSConfig_file = `
29+
provider "jetstream" {
30+
servers = "%s"
31+
tls {
32+
ca_file = "%s"
33+
}
34+
}
35+
36+
resource "jetstream_stream" "test" {
37+
name = "TEST"
38+
subjects = ["TEST.*"]
39+
}
40+
`
41+
42+
func TestProviderWithTLSFromData(t *testing.T) {
43+
srv := createJSTLSServer(t)
44+
defer srv.Shutdown()
45+
46+
caFile, cleanup, err := newTempPEMFile(caPEM)
47+
48+
if err != nil {
49+
t.Fatalf("failed to create temp CA PEM: %s", err)
50+
}
51+
defer cleanup()
52+
53+
nc, err := nats.Connect(srv.ClientURL(), nats.RootCAs(caFile))
54+
if err != nil {
55+
t.Fatalf("could not connect: %s", err)
56+
}
57+
defer nc.Close()
58+
59+
mgr, err := jsm.New(nc)
60+
if err != nil {
61+
t.Fatalf("could not connect: %s", err)
62+
}
63+
64+
resource.Test(t, resource.TestCase{
65+
Providers: testJsProviders,
66+
Steps: []resource.TestStep{
67+
{
68+
Config: fmt.Sprintf(testTLSConfig_file_data, nc.ConnectedUrl(), caPEM),
69+
Check: resource.ComposeTestCheckFunc(
70+
testStreamExist(t, mgr, "TEST"),
71+
),
72+
},
73+
},
74+
})
75+
}
76+
77+
func TestProviderWithTLSFromFile(t *testing.T) {
78+
srv := createJSTLSServer(t)
79+
defer srv.Shutdown()
80+
81+
caFile, cleanup, err := newTempPEMFile(caPEM)
82+
if err != nil {
83+
t.Fatalf("failed to create temp CA PEM: %s", err)
84+
}
85+
defer cleanup()
86+
87+
nc, err := nats.Connect(srv.ClientURL(), nats.RootCAs(caFile))
88+
if err != nil {
89+
t.Fatalf("could not connect: %s", err)
90+
}
91+
defer nc.Close()
92+
93+
mgr, err := jsm.New(nc)
94+
if err != nil {
95+
t.Fatalf("could not connect: %s", err)
96+
}
97+
98+
resource.Test(t, resource.TestCase{
99+
Providers: testJsProviders,
100+
Steps: []resource.TestStep{
101+
{
102+
Config: fmt.Sprintf(testTLSConfig_file, nc.ConnectedUrl(), caFile),
103+
Check: resource.ComposeTestCheckFunc(
104+
testStreamExist(t, mgr, "TEST"),
105+
),
106+
},
107+
},
108+
})
109+
}

0 commit comments

Comments
 (0)