diff --git a/glauth/pkg/command/server.go b/glauth/pkg/command/server.go index 3fa6d6db50..5a2f1f10d1 100644 --- a/glauth/pkg/command/server.go +++ b/glauth/pkg/command/server.go @@ -9,12 +9,12 @@ import ( "github.com/oklog/run" accounts "github.com/owncloud/ocis/accounts/pkg/proto/v0" "github.com/owncloud/ocis/glauth/pkg/config" - "github.com/owncloud/ocis/glauth/pkg/crypto" "github.com/owncloud/ocis/glauth/pkg/flagset" "github.com/owncloud/ocis/glauth/pkg/metrics" "github.com/owncloud/ocis/glauth/pkg/server/debug" "github.com/owncloud/ocis/glauth/pkg/server/glauth" "github.com/owncloud/ocis/glauth/pkg/tracing" + pkgcrypto "github.com/owncloud/ocis/ocis-pkg/crypto" "github.com/owncloud/ocis/ocis-pkg/service/grpc" "github.com/owncloud/ocis/ocis-pkg/sync" ) @@ -100,7 +100,7 @@ func Server(cfg *config.Config) *cli.Command { } if lscfg.Enabled { - if err := crypto.GenCert(cfg.Ldaps.Cert, cfg.Ldaps.Key, logger); err != nil { + if err := pkgcrypto.GenCert(cfg.Ldaps.Cert, cfg.Ldaps.Key, logger); err != nil { logger.Fatal().Err(err).Msgf("Could not generate test-certificate") } } diff --git a/idp/pkg/crypto/gencert.go b/idp/pkg/crypto/gencert.go deleted file mode 100644 index 3a287d5f7e..0000000000 --- a/idp/pkg/crypto/gencert.go +++ /dev/null @@ -1,144 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "math/big" - "net" - "os" - "path/filepath" - "time" - - "github.com/owncloud/ocis/ocis-pkg/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 and persists them to the filesystem. -func GenCert(certName string, keyName string, l log.Logger) error { - var priv interface{} - var err error - - _, certErr := os.Stat(certName) - _, keyErr := os.Stat(keyName) - - if certErr == nil || keyErr == nil { - l.Debug().Msg("IDP certificate or key already present, using these") - return nil - } - - 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) - } - } - - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create certificate") - } - - certPath := filepath.Dir(certName) - if _, err := os.Stat(certPath); os.IsNotExist(err) { - err = os.MkdirAll(certPath, 0700) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create path " + certPath) - } - } - - certOut, err := os.Create(certName) - 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") - - keyPath := filepath.Dir(keyName) - if _, err := os.Stat(keyPath); os.IsNotExist(err) { - err = os.MkdirAll(keyPath, 0700) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create path " + keyPath) - } - } - - keyOut, err := os.OpenFile(keyName, 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 -} diff --git a/idp/pkg/server/http/server.go b/idp/pkg/server/http/server.go index 279de2e494..9a911f4e84 100644 --- a/idp/pkg/server/http/server.go +++ b/idp/pkg/server/http/server.go @@ -5,9 +5,8 @@ import ( "os" "github.com/asim/go-micro/v3" - - "github.com/owncloud/ocis/idp/pkg/crypto" svc "github.com/owncloud/ocis/idp/pkg/service/v0" + pkgcrypto "github.com/owncloud/ocis/ocis-pkg/crypto" "github.com/owncloud/ocis/ocis-pkg/middleware" "github.com/owncloud/ocis/ocis-pkg/service/http" ) @@ -24,7 +23,7 @@ func Server(opts ...Option) (http.Service, error) { if os.IsNotExist(certErr) || os.IsNotExist(keyErr) { options.Logger.Info().Msgf("Generating certs") - if err := crypto.GenCert(options.Config.HTTP.TLSCert, options.Config.HTTP.TLSKey, options.Logger); err != nil { + if err := pkgcrypto.GenCert(options.Config.HTTP.TLSCert, options.Config.HTTP.TLSKey, options.Logger); err != nil { options.Logger.Fatal().Err(err).Msg("Could not setup TLS") os.Exit(1) } diff --git a/glauth/pkg/crypto/gencert.go b/ocis-pkg/crypto/gencert.go similarity index 58% rename from glauth/pkg/crypto/gencert.go rename to ocis-pkg/crypto/gencert.go index ceea464f83..d16371cb68 100644 --- a/glauth/pkg/crypto/gencert.go +++ b/ocis-pkg/crypto/gencert.go @@ -7,6 +7,7 @@ import ( "crypto/x509" "crypto/x509/pkix" "encoding/pem" + "fmt" "math/big" "net" "os" @@ -44,30 +45,85 @@ func pemBlockForKey(priv interface{}, l log.Logger) *pem.Block { // GenCert generates TLS-Certificates func GenCert(certName string, keyName string, l log.Logger) error { - var priv interface{} + var pk *rsa.PrivateKey var err error + pk, err = rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return err + } + + // if either the key or certificate already exist skip this entire ordeal _, certErr := os.Stat(certName) _, keyErr := os.Stat(keyName) if certErr == nil || keyErr == nil { - l.Debug().Msg("LDAPS certificate or key already present, using these") + l.Debug().Msg(fmt.Sprintf("%v certificate or key already present, using these", filepath.Base(certName))) return nil } - priv, err = rsa.GenerateKey(rand.Reader, 2048) + persistCertificate(certName, l, pk) + persistKey(keyName, l, pk) + return nil +} - if err != nil { - l.Fatal().Err(err).Msg("Failed to generate private key") +func persistCertificate(certName string, l log.Logger, pk *rsa.PrivateKey) { + if err := ensureExistsDir(certName); err != nil { + l.Fatal().Err(err).Msg("creating certificate destination: " + certName) } + certificate, err := generateCertificate(pk) + if err != nil { + l.Fatal().Err(err).Msg("creating certificate: " + filepath.Dir(certName)) + } + + certOut, err := os.Create(certName) + if err != nil { + l.Fatal().Err(err).Msgf("failed to open `%v` for writing", certName) + } + + err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: certificate}) + 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(fmt.Sprintf("written certificate to %v", certName)) +} + +func persistKey(keyName string, l log.Logger, pk *rsa.PrivateKey) { + if err := ensureExistsDir(keyName); err != nil { + l.Fatal().Err(err).Msg("creating certificate destination: " + keyName) + } + + keyOut, err := os.OpenFile(keyName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + l.Fatal().Err(err).Msgf("failed to open %v for writing", keyName) + } + err = pem.Encode(keyOut, pemBlockForKey(pk, 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(fmt.Sprintf("written key to %v", keyName)) +} + +// genCert generates a self signed certificate using a random rsa key. +func generateCertificate(pk *rsa.PrivateKey) ([]byte, error) { 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") + return nil, err } template := x509.Certificate{ @@ -93,56 +149,16 @@ func GenCert(certName string, keyName string, l log.Logger) error { } } - //template.IsCA = true - //template.KeyUsage |= x509.KeyUsageCertSign + return x509.CreateCertificate(rand.Reader, &template, &template, publicKey(pk), pk) +} - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create certificate") - } - - certPath := filepath.Dir(certName) +func ensureExistsDir(uri string) error { + certPath := filepath.Dir(uri) if _, err := os.Stat(certPath); os.IsNotExist(err) { err = os.MkdirAll(certPath, 0700) if err != nil { - l.Fatal().Err(err).Msg("Failed to create path " + certPath) + return err } } - - certOut, err := os.Create(certName) - if err != nil { - l.Fatal().Err(err).Msgf("Failed to open %v for writing", certName) - } - 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") - - keyPath := filepath.Dir(keyName) - if _, err := os.Stat(keyPath); os.IsNotExist(err) { - err = os.MkdirAll(keyPath, 0700) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create path " + keyPath) - } - } - - keyOut, err := os.OpenFile(keyName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - l.Fatal().Err(err).Msgf("Failed to open %v for writing", keyName) - } - 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().Msgf("Written %v", keyName) return nil } diff --git a/proxy/pkg/crypto/gencert.go b/proxy/pkg/crypto/gencert.go deleted file mode 100644 index 3af9169c79..0000000000 --- a/proxy/pkg/crypto/gencert.go +++ /dev/null @@ -1,144 +0,0 @@ -package crypto - -import ( - "crypto/ecdsa" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "math/big" - "net" - "os" - "path/filepath" - "time" - - "github.com/owncloud/ocis/ocis-pkg/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 and persists them to the filesystem. -func GenCert(certName string, keyName string, l log.Logger) error { - var priv interface{} - var err error - - _, certErr := os.Stat(certName) - _, keyErr := os.Stat(keyName) - - if certErr == nil || keyErr == nil { - l.Debug().Msg("Proxy certificate or key already present, using these") - return nil - } - - 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) - } - } - - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create certificate") - } - - certPath := filepath.Dir(certName) - if _, err := os.Stat(certPath); os.IsNotExist(err) { - err = os.MkdirAll(certPath, 0700) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create path " + certPath) - } - } - - certOut, err := os.Create(certName) - 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") - - keyPath := filepath.Dir(keyName) - if _, err := os.Stat(keyPath); os.IsNotExist(err) { - err = os.MkdirAll(keyPath, 0700) - if err != nil { - l.Fatal().Err(err).Msg("Failed to create path " + keyPath) - } - } - - keyOut, err := os.OpenFile(keyName, 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 -} diff --git a/proxy/pkg/server/http/server.go b/proxy/pkg/server/http/server.go index 57985361dd..0ac865f16f 100644 --- a/proxy/pkg/server/http/server.go +++ b/proxy/pkg/server/http/server.go @@ -5,9 +5,8 @@ import ( "os" "github.com/asim/go-micro/v3" - + pkgcrypto "github.com/owncloud/ocis/ocis-pkg/crypto" svc "github.com/owncloud/ocis/ocis-pkg/service/http" - "github.com/owncloud/ocis/proxy/pkg/crypto" ) // Server initializes the http service and server. @@ -26,7 +25,7 @@ func Server(opts ...Option) (svc.Service, error) { if os.IsNotExist(certErr) || os.IsNotExist(keyErr) { // GenCert has side effects as it writes 2 files to the binary running location - if err := crypto.GenCert(httpCfg.TLSCert, httpCfg.TLSKey, l); err != nil { + if err := pkgcrypto.GenCert(httpCfg.TLSCert, httpCfg.TLSKey, l); err != nil { l.Fatal().Err(err).Msgf("Could not generate test-certificate") os.Exit(1) }