$ go get github.com/cloudflare/cfssl/cmd/cfssl@v1.4.1
$ go get github.com/cloudflare/cfssl/cmd/cfssljson@v1.4.1
proglog/test/ca-csr.json
{
"CN": "My Awesome CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CA",
"L": "ON",
"ST": "Toronto",
"O": "My Awesome Company",
"OU": "CA Services"
}
]
}
{
"signing": {
"profiles": {
"server": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
}
}
}
}
{
"CN": "127.0.0.1",
"hosts": [
"127.0.0.1",
"localhost"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CA",
"L": "ON",
"ST": "Toronto",
"O": "My Awesome Company",
"OU": "Distributed Services"
}
]
}
CONFIG_PATH=${HOME}/.proglog/
init:
mkdir -p ${CONFIG_PATH}
.PHONY: gencert
gencert:
cfssl gencert -initca test/ca-csr.json | cfssljson -bare ca
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=test/ca-config.json -profile=server test/server-csr.json | cfssljson -bare server
mv *.pem *.csr ${CONFIG_PATH}
package config
import (
"os"
"path/filepath"
)
var (
CAFile = configFile("ca.pem")
ServerCertFile = configFile("server.pem")
ServerKeyFile = configFile("server-key.pem")
)
func configFile(fileName string) string {
if dir := os.Getenv("CONFIG_DIR"); dir != "" {
return filepath.Join(dir, fileName)
}
homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
return filepath.Join(homeDir, "/.proglog/", fileName)
}
package config
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
)
type TLSConfig struct {
CertFile string
KeyFile string
CAFile string
ServerAddress string
Server bool
}
func SetupTLSConfig(cfg TLSConfig) (*tls.Config, error) {
var err error
tlsConfig := &tls.Config{}
if cfg.CertFile != "" && cfg.KeyFile != "" {
tlsConfig.Certificates = make([]tls.Certificate, 1)
tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(cfg.CertFile, cfg.KeyFile)
if err != nil {
return nil, err
}
}
if cfg.CAFile != "" {
b, err := ioutil.ReadFile(CAFile)
if err != nil {
return nil, err
}
ca := x509.NewCertPool()
ok := ca.AppendCertsFromPEM([]byte(b))
if !ok {
return nil, fmt.Errorf("failed to parse root certifacte: %q", cfg.CAFile)
}
if cfg.Server {
tlsConfig.ClientCAs = ca
tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
} else {
tlsConfig.RootCAs = ca
}
tlsConfig.ServerName = cfg.ServerAddress
}
return tlsConfig, nil
}
proglog/internal/server/server_test.go
t.Helper()
l, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
clientTLSConfig, err := config.SetupTLSConfig(config.TLSConfig{
CAFile: config.CAFile,
})
require.NoError(t, err)
clientCreds := credentials.NewTLS(clientTLSConfig)
cc, err := grpc.Dial(l.Addr().String(), grpc.WithTransportCredentials(clientCreds))
require.NoError(t, err)
client := api.NewLogClient(cc)
serverTLSConfig, err := config.SetupTLSConfig(config.TLSConfig{
CAFile: config.CAFile,
CertFile: config.ServerCertFile,
KeyFile: config.ServerKeyFile,
ServerAddress: l.Addr().String(),
Server: true,
})
require.NoError(t, err)
serverCreds := credentials.NewTLS(serverTLSConfig)
dir, err := ioutil.TempDir("", "server-test")
require.NoError(t, err)
cLog, err := log.NewLog(dir, log.Config{})
require.NoError(t, err)
cfg = &Config{CommitLog: cLog}
if fn != nil {
fn(cfg)
}
server, err := NewGRPCServer(cfg, grpc.Creds(serverCreds))
require.NoError(t, err)
go func() {
server.Serve(l)
}()
return client, cfg, func(){
server.Stop()
cc.Close()
l.Close()
}
func NewGRPCServer(config *Config, opts ...grpc.ServerOption) (*grpc.Server, error) {
gsrv := grpc.NewServer(opts...)
srv, err := newgrpcServer(config)
if err != nil {
return nil, err
}
api.RegisterLogServer(gsrv, srv)
return gsrv, nil
}