2021-07-17 14:38:59 +02:00
package cmd
import (
2021-08-07 12:26:07 +02:00
"context"
2021-09-25 19:22:49 +02:00
"crypto/tls"
2021-07-17 14:38:59 +02:00
"flag"
"fmt"
2021-07-30 17:46:38 +02:00
"github.com/wiretrustee/wiretrustee/management/server"
2021-08-07 13:51:17 +02:00
"github.com/wiretrustee/wiretrustee/management/server/http"
2021-07-30 17:46:38 +02:00
"github.com/wiretrustee/wiretrustee/util"
2021-07-24 16:14:29 +02:00
"net"
"os"
"time"
2021-07-17 14:38:59 +02:00
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
2021-07-22 15:23:24 +02:00
"github.com/wiretrustee/wiretrustee/encryption"
2021-07-17 14:38:59 +02:00
mgmtProto "github.com/wiretrustee/wiretrustee/management/proto"
"google.golang.org/grpc"
2021-07-17 14:51:16 +02:00
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/keepalive"
2021-07-17 14:38:59 +02:00
)
var (
2021-07-17 14:51:16 +02:00
mgmtPort int
mgmtDataDir string
2021-07-30 17:46:38 +02:00
mgmtConfig string
2021-07-17 14:51:16 +02:00
mgmtLetsencryptDomain string
2021-09-25 19:22:49 +02:00
certFile string
certKey string
2021-07-17 14:51:16 +02:00
kaep = keepalive . EnforcementPolicy {
2021-07-22 10:28:00 +02:00
MinTime : 15 * time . Second ,
2021-07-17 14:51:16 +02:00
PermitWithoutStream : true ,
}
kasp = keepalive . ServerParameters {
MaxConnectionIdle : 15 * time . Second ,
MaxConnectionAgeGrace : 5 * time . Second ,
Time : 5 * time . Second ,
Timeout : 2 * time . Second ,
}
2021-07-17 14:38:59 +02:00
mgmtCmd = & cobra . Command {
Use : "management" ,
Short : "start Wiretrustee Management Server" ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
flag . Parse ( )
2021-09-07 09:53:18 +02:00
err := util . InitLog ( logLevel , logFile )
if err != nil {
log . Fatalf ( "failed initializing log %v" , err )
}
2021-07-17 14:38:59 +02:00
2021-07-30 17:46:38 +02:00
config , err := loadConfig ( )
if err != nil {
log . Fatalf ( "failed reading provided config file: %s: %v" , mgmtConfig , err )
}
if _ , err = os . Stat ( config . Datadir ) ; os . IsNotExist ( err ) {
err = os . MkdirAll ( config . Datadir , os . ModeDir )
2021-07-17 17:26:51 +02:00
if err != nil {
2021-07-30 17:46:38 +02:00
log . Fatalf ( "failed creating datadir: %s: %v" , config . Datadir , err )
2021-07-17 17:26:51 +02:00
}
2021-07-17 14:38:59 +02:00
}
2021-08-12 12:49:10 +02:00
store , err := server . NewStore ( config . Datadir )
if err != nil {
log . Fatalf ( "failed creating a store: %s: %v" , config . Datadir , err )
}
2021-09-07 18:36:46 +02:00
peersUpdateManager := server . NewPeersUpdateManager ( )
accountManager := server . NewManager ( store , peersUpdateManager )
2021-08-12 12:49:10 +02:00
2021-07-17 14:51:16 +02:00
var opts [ ] grpc . ServerOption
2021-08-07 13:51:17 +02:00
var httpServer * http . Server
2021-08-07 13:35:52 +02:00
if config . HttpConfig . LetsEncryptDomain != "" {
2021-09-25 19:22:49 +02:00
//automatically generate a new certificate with Let's Encrypt
2021-08-07 13:35:52 +02:00
certManager := encryption . CreateCertManager ( config . Datadir , config . HttpConfig . LetsEncryptDomain )
2021-08-07 12:26:07 +02:00
transportCredentials := credentials . NewTLS ( certManager . TLSConfig ( ) )
2021-07-22 15:23:24 +02:00
opts = append ( opts , grpc . Creds ( transportCredentials ) )
2021-08-07 12:26:07 +02:00
2021-08-12 12:49:10 +02:00
httpServer = http . NewHttpsServer ( config . HttpConfig , certManager , accountManager )
2021-09-25 19:22:49 +02:00
} else if config . HttpConfig . CertFile != "" && config . HttpConfig . CertKey != "" {
//use provided certificate
tlsConfig , err := loadTLSConfig ( config . HttpConfig . CertFile , config . HttpConfig . CertKey )
if err != nil {
log . Fatal ( "cannot load TLS credentials: " , err )
}
transportCredentials := credentials . NewTLS ( tlsConfig )
opts = append ( opts , grpc . Creds ( transportCredentials ) )
httpServer = http . NewHttpsServerWithTLSConfig ( config . HttpConfig , tlsConfig , accountManager )
2021-08-07 12:26:07 +02:00
} else {
2021-09-25 19:22:49 +02:00
//start server without SSL
2021-08-12 12:49:10 +02:00
httpServer = http . NewHttpServer ( config . HttpConfig , accountManager )
2021-07-17 14:38:59 +02:00
}
2021-07-17 14:51:16 +02:00
opts = append ( opts , grpc . KeepaliveEnforcementPolicy ( kaep ) , grpc . KeepaliveParams ( kasp ) )
2021-07-17 14:38:59 +02:00
grpcServer := grpc . NewServer ( opts ... )
2021-09-02 14:41:54 +02:00
turnManager := server . NewTimeBasedAuthSecretsManager ( peersUpdateManager , config . TURNConfig )
server , err := server . NewServer ( config , accountManager , peersUpdateManager , turnManager )
2021-07-17 14:38:59 +02:00
if err != nil {
log . Fatalf ( "failed creating new server: %v" , err )
}
mgmtProto . RegisterManagementServiceServer ( grpcServer , server )
log . Printf ( "started server: localhost:%v" , mgmtPort )
2021-07-17 14:51:16 +02:00
lis , err := net . Listen ( "tcp" , fmt . Sprintf ( ":%d" , mgmtPort ) )
if err != nil {
log . Fatalf ( "failed to listen: %v" , err )
}
2021-07-17 14:38:59 +02:00
go func ( ) {
if err = grpcServer . Serve ( lis ) ; err != nil {
2021-07-17 14:51:16 +02:00
log . Fatalf ( "failed to serve gRpc server: %v" , err )
2021-07-17 14:38:59 +02:00
}
} ( )
2021-08-07 12:26:07 +02:00
go func ( ) {
err = httpServer . Start ( )
if err != nil {
log . Fatalf ( "failed to serve http server: %v" , err )
}
} ( )
2021-07-17 14:38:59 +02:00
SetupCloseHandler ( )
<- stopCh
log . Println ( "Receive signal to stop running Management server" )
2021-08-07 12:26:07 +02:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 10 * time . Second )
defer cancel ( )
err = httpServer . Stop ( ctx )
if err != nil {
log . Fatalf ( "failed stopping the http server %v" , err )
}
grpcServer . Stop ( )
2021-07-17 14:38:59 +02:00
} ,
}
)
2021-07-30 17:46:38 +02:00
func loadConfig ( ) ( * server . Config , error ) {
config := & server . Config { }
_ , err := util . ReadJson ( mgmtConfig , config )
if err != nil {
return nil , err
}
if mgmtLetsencryptDomain != "" {
2021-08-07 13:35:52 +02:00
config . HttpConfig . LetsEncryptDomain = mgmtLetsencryptDomain
2021-07-30 17:46:38 +02:00
}
if mgmtDataDir != "" {
config . Datadir = mgmtDataDir
}
2021-09-25 19:22:49 +02:00
if certKey != "" && certFile != "" {
config . HttpConfig . CertFile = certFile
config . HttpConfig . CertKey = certKey
}
2021-07-30 17:46:38 +02:00
return config , err
}
2021-09-25 19:22:49 +02:00
func loadTLSConfig ( certFile string , certKey string ) ( * tls . Config , error ) {
// Load server's certificate and private key
serverCert , err := tls . LoadX509KeyPair ( certFile , certKey )
if err != nil {
return nil , err
}
// Create the credentials and return it
config := & tls . Config {
Certificates : [ ] tls . Certificate { serverCert } ,
ClientAuth : tls . NoClientCert ,
}
return config , nil
}
2021-07-17 14:38:59 +02:00
func init ( ) {
2021-07-17 14:51:16 +02:00
mgmtCmd . Flags ( ) . IntVar ( & mgmtPort , "port" , 33073 , "server port to listen on" )
2021-07-17 15:47:16 +02:00
mgmtCmd . Flags ( ) . StringVar ( & mgmtDataDir , "datadir" , "/var/lib/wiretrustee/" , "server data directory location" )
2021-07-30 17:46:38 +02:00
mgmtCmd . Flags ( ) . StringVar ( & mgmtConfig , "config" , "/etc/wiretrustee/management.json" , "Wiretrustee config file location. Config params specified via command line (e.g. datadir) have a precedence over configuration from this file" )
2021-07-17 14:51:16 +02:00
mgmtCmd . Flags ( ) . StringVar ( & mgmtLetsencryptDomain , "letsencrypt-domain" , "" , "a domain to issue Let's Encrypt certificate for. Enables TLS using Let's Encrypt. Will fetch and renew certificate, and run the server with TLS" )
2021-09-25 19:22:49 +02:00
mgmtCmd . Flags ( ) . StringVar ( & certFile , "cert-file" , "" , "Location of your SSL certificate. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect" )
mgmtCmd . Flags ( ) . StringVar ( & certKey , "cert-key" , "" , "Location of your SSL certificate private key. Can be used when you have an existing certificate and don't want a new certificate be generated automatically. If letsencrypt-domain is specified this property has no effect" )
2021-07-30 17:46:38 +02:00
rootCmd . MarkFlagRequired ( "config" ) //nolint
2021-07-17 14:38:59 +02:00
}