Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5. Certificate Authority #5

Open
wants to merge 6 commits into
base: 3-test-random
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,69 @@ func TestMyApp(t *testing.T) {
}
```

For a full list of possible functions, please [check the Go docs](https://pkg.go.dev/github.com/opentofu/tofutestutils).
For a full list of possible functions, please [check the Go docs](https://pkg.go.dev/github.com/opentofu/tofutestutils).

## Certificate authority

When you need an x509 certificate for a server or a client, you can use the `tofutestutils.CA` function to obtain a `testca.CertificateAuthority` implementation using a pseudo-random number generator. You can use this to create a certificate for a socket server:

```go
package your_test

import (
"crypto/tls"
"io"
"net"
"strconv"
"testing"

"github.com/opentofu/tofutestutils"
)

func TestMySocket(t *testing.T) {
ca := tofutestutils.CA(t)

// Server side:
tlsListener, err := tls.Listen("tcp", "127.0.0.1:0", ca.CreateLocalhostServerCert().GetServerTLSConfig())
if err != nil {
t.Fatalf("Failed to open server: %v", err)
}
defer func() {
if err = tlsListener.Close(); err != nil {
t.Fatalf("Failed to close server listener: %v", err)
}
}()
go func() {
conn, serverErr := tlsListener.Accept()
if serverErr != nil {
return
}
defer func() {
if err := conn.Close(); err != nil {
t.Logf("Failed to close connection: %v", err)
}
}()
if _, err = conn.Write([]byte("Hello world!")); err != nil {
t.Logf("Failed to write to client: %v", err)
}
}()

// Client side:
port := tlsListener.Addr().(*net.TCPAddr).Port
client, err := tls.Dial("tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(port)), ca.GetClientTLSConfig())
if err != nil {
t.Fatalf("Failed to open connection to server: %v", err)
}
defer func() {
if err = client.Close(); err != nil {
t.Fatalf("Failed to close client: %v", err)
}
}()

data, err := io.ReadAll(client)
if err != nil {
t.Fatal(err)
}
t.Logf("%s", data)
}
```
18 changes: 18 additions & 0 deletions ca.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package tofutestutils

import (
"testing"

"github.com/opentofu/tofutestutils/testca"
)

// CA returns a certificate authority configured for the provided test. This implementation will configure the CA to use
// a pseudorandom source. You can call testca.New() for more configuration options.
func CA(t *testing.T) testca.CertificateAuthority {
return testca.New(t, RandomSource())
}
48 changes: 48 additions & 0 deletions testca/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Certificate authority

This folder contains a basic x509 certificate authority implementation for testing purposes. You can use it whenever you need a certificate for servers or clients.

```go
package your_test

import (
"crypto/tls"
"io"
"net"
"strconv"
"testing"
"time"

"github.com/opentofu/tofutestutils"
"github.com/opentofu/tofutestutils/testca"
"github.com/opentofu/tofutestutils/testrandom"
)

func TestMySocket(t *testing.T) {
// Configure a desired randomness and time source. You can use this to create deterministic behavior.
currentTimeSource := time.Now
ca := testca.New(t, testrandom.DeterministicSource(t), currentTimeSource)

// Server side:
tlsListener := tofutestutils.Must2(tls.Listen("tcp", "127.0.0.1:0", ca.CreateLocalhostServerCert().GetServerTLSConfig()))
go func() {
conn, serverErr := tlsListener.Accept()
if serverErr != nil {
return
}
defer func() {
_ = conn.Close()
}()
_, _ = conn.Write([]byte("Hello world!"))
}()

// Client side:
port := tlsListener.Addr().(*net.TCPAddr).Port
client := tofutestutils.Must2(tls.Dial("tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(port)), ca.GetClientTLSConfig()))
defer func() {
_ = client.Close()
abstractionfactory marked this conversation as resolved.
Show resolved Hide resolved
}()

t.Logf("%s", tofutestutils.Must2(io.ReadAll(client)))
}
```
Loading
Loading