Skip to content
This repository has been archived by the owner on Jan 27, 2021. It is now read-only.

Commit

Permalink
Make TLS-Certificate configurable
Browse files Browse the repository at this point in the history
Currently the proxy generates certificates on every start for dev purposes. This commit adds an option to make this behaviour configurable.
This also removes the dependency on konnectd`s crypto code and copies it instead, as this library is a first version which is not meant for usage by other services.

A proper cert-generation lib should be added to ocis-pkg instead. Then this code can be refactored to use it.
  • Loading branch information
IljaN committed Mar 19, 2020
1 parent 5888e10 commit c8a9f21
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 108 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/tls-cert-configurable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Make TLS-Cert configurable

Before a generates certificates on every start was used for dev purposes.

https://github.com/owncloud/ocis-proxy/pull/14
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ require (
contrib.go.opencensus.io/exporter/jaeger v0.2.0
contrib.go.opencensus.io/exporter/ocagent v0.6.0
contrib.go.opencensus.io/exporter/zipkin v0.1.1
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 // indirect
github.com/micro/cli/v2 v2.1.2-0.20200203150404-894195727d9c
github.com/micro/go-micro/v2 v2.0.1-0.20200212105717-d76baf59de2e // indirect
github.com/oklog/run v1.1.0
github.com/openzipkin/zipkin-go v0.2.2
github.com/owncloud/ocis-konnectd v0.0.0-20200303180152-937016f63393
github.com/owncloud/ocis-pkg/v2 v2.0.2
github.com/prometheus/client_golang v1.2.1
github.com/prometheus/procfs v0.0.8 // indirect
github.com/restic/calens v0.2.0
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/viper v1.6.2
go.opencensus.io v0.22.2
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6 // indirect
golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
gopkg.in/square/go-jose.v2 v2.4.0 // indirect
gopkg.in/yaml.v2 v2.2.7 // indirect
)
95 changes: 0 additions & 95 deletions go.sum

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ type HTTP struct {
Addr string
Namespace string
Root string
TLSCert string
TLSKey string
}

// Tracing defines the available tracing configuration.
Expand Down
123 changes: 123 additions & 0 deletions pkg/crypto/gencert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package crypto

import (
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"net"
"os"
"time"

"github.com/owncloud/ocis-pkg/v2/log"
)

func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}

func pemBlockForKey(priv interface{}, l log.Logger) *pem.Block {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
case *ecdsa.PrivateKey:
b, err := x509.MarshalECPrivateKey(k)
if err != nil {
l.Fatal().Err(err).Msg("Unable to marshal ECDSA private key")
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}
default:
return nil
}
}

// GenCert generates TLS-Certificates
func GenCert(l log.Logger) error {
var priv interface{}
var err error

priv, err = rsa.GenerateKey(rand.Reader, 2048)

if err != nil {
l.Fatal().Err(err).Msg("Failed to generate private key")
}

notBefore := time.Now()
notAfter := notBefore.Add(24 * time.Hour * 365)

serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
l.Fatal().Err(err).Msg("Failed to generate serial number")
}

template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"Acme Corp"},
CommonName: "OCIS",
},
NotBefore: notBefore,
NotAfter: notAfter,

KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
}

hosts := []string{"127.0.0.1", "localhost"}
for _, h := range hosts {
if ip := net.ParseIP(h); ip != nil {
template.IPAddresses = append(template.IPAddresses, ip)
} else {
template.DNSNames = append(template.DNSNames, h)
}
}

//template.IsCA = true
//template.KeyUsage |= x509.KeyUsageCertSign

derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv)
if err != nil {
l.Fatal().Err(err).Msg("Failed to create certificate")
}

certOut, err := os.Create("server.crt")
if err != nil {
l.Fatal().Err(err).Msg("Failed to open server.crt for writing")
}
err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
if err != nil {
l.Fatal().Err(err).Msg("Failed to encode certificate")
}
err = certOut.Close()
if err != nil {
l.Fatal().Err(err).Msg("Failed to write cert")
}
l.Info().Msg("Written server.crt")

keyOut, err := os.OpenFile("server.key", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
l.Fatal().Err(err).Msg("Failed to open server.key for writing")
}
err = pem.Encode(keyOut, pemBlockForKey(priv, l))
if err != nil {
l.Fatal().Err(err).Msg("Failed to encode key")
}
err = keyOut.Close()
if err != nil {
l.Fatal().Err(err).Msg("Failed to write key")
}
l.Info().Msg("Written server.key")
return nil
}
14 changes: 14 additions & 0 deletions pkg/flagset/flagset.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,19 @@ func ServerWithConfig(cfg *config.Config) []cli.Flag {
EnvVars: []string{"PROXY_HTTP_NAMESPACE"},
Destination: &cfg.HTTP.Namespace,
},
&cli.StringFlag{
Name: "transport-tls-cert",
Value: "",
Usage: "Certificate file for transport encryption",
EnvVars: []string{"PROXY_TRANSPORT_TLS_CERT"},
Destination: &cfg.HTTP.TLSCert,
},
&cli.StringFlag{
Name: "transport-tls-key",
Value: "",
Usage: "Secret file for transport encryption",
EnvVars: []string{"PROXY_TRANSPORT_TLS_KEY"},
Destination: &cfg.HTTP.TLSKey,
},
}
}
38 changes: 27 additions & 11 deletions pkg/server/http/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,46 @@ package http

import (
"crypto/tls"
"os"

occrypto "github.com/owncloud/ocis-konnectd/pkg/crypto"
svc "github.com/owncloud/ocis-pkg/v2/service/http"
"github.com/owncloud/ocis-proxy/pkg/crypto"
"github.com/owncloud/ocis-proxy/pkg/version"
"os"
)

// Server initializes the http service and server.
func Server(opts ...Option) (svc.Service, error) {
options := newOptions(opts...)
l := options.Logger
httpCfg := options.Config.HTTP

var cer tls.Certificate
var certErr error

if httpCfg.TLSCert == "" || httpCfg.TLSKey == "" {
l.Warn().Msgf("No tls certificate provided, using a generated one")

// GenCert has side effects as it writes 2 files to the binary running location
occrypto.GenCert(options.Logger)
// GenCert has side effects as it writes 2 files to the binary running location
if err := crypto.GenCert(l); err != nil {
l.Fatal().Err(err).Msgf("Could not generate test-certificate")
}

cer, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
options.Logger.Fatal().Err(err).Msg("Could not setup TLS")
httpCfg.TLSKey = "server.crt"
httpCfg.TLSKey = "server.key"
}

cer, certErr = tls.LoadX509KeyPair(httpCfg.TLSCert, httpCfg.TLSKey)

if certErr != nil {
options.Logger.Fatal().Err(certErr).Msg("Could not setup TLS")
os.Exit(1)
}

config := &tls.Config{Certificates: []tls.Certificate{cer}}
tlsConfig := &tls.Config{Certificates: []tls.Certificate{cer}}

service := svc.NewService(
svc.Name("web.proxy"),
svc.Handler(options.Handler),
svc.TLSConfig(config),
svc.TLSConfig(tlsConfig),
svc.Logger(options.Logger),
svc.Namespace(options.Namespace),
svc.Version(version.String),
Expand All @@ -36,7 +50,9 @@ func Server(opts ...Option) (svc.Service, error) {
svc.Flags(options.Flags...),
)

service.Init()
if err := service.Init(); err != nil {
l.Fatal().Err(err).Msgf("Error initializing")
}

return service, nil
}

0 comments on commit c8a9f21

Please sign in to comment.