diff --git a/docker-compose.payments.yml b/docker-compose.payments.yml new file mode 100644 index 000000000..7057b5f6b --- /dev/null +++ b/docker-compose.payments.yml @@ -0,0 +1,55 @@ +services: + redis: + image: redis:7.0 + restart: always + #ports: + # - '6379:6379' + command: redis-server --save 20 1 --loglevel verbose --requirepass idBocFijvo --user redis + #volumes: + # - redis-cache:/data + +# Access to localstack: +# export AWS_DEFAULT_REGION=us-east-1 +# export AWS_SECRET_ACCESS_KEY=test +# export AWS_ACCESS_KEY_ID=test +# export AWS_ENDPOINT_URL=http://localhost:4566 + + localstack: + container_name: localstack + image: localstack/localstack + ports: + - "127.0.0.1:4566:4566" # LocalStack Gateway + - "127.0.0.1:4510-4559:4510-4559" # external services port range + environment: + # LocalStack configuration: https://docs.localstack.cloud/references/configuration/ + - DEBUG=0 + #volumes: + #- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" + # Access to Docker is not necessary with S3. + # - "/var/run/docker.sock:/var/run/docker.sock" + + worker: + image: bat-go-repro:latest + command: bat-go serve payments worker + environment: + - REDIS_ADDR=redis:6379 + - REDIS_USER=user + - REDIS_PASS=idBocFijvo + - DEBUG=1 + - ENVIRONMENT=development + - NITRO_API_BASE=http://web.payment-dev.svc.cluster.local + + service: + image: bat-go-repro:latest + command: bat-go serve nitro inside-enclave --egress-address none --log-address none --upstream-url http://0.0.0.0:8080 + environment: + - ENCLAVE_MOCKING=1 + - AWS_REGION="us-west-2" + - DEBUG=1 + ports: + - "18080:8080" + - "18443:8443" + +volumes: + redis-cache: + driver: local diff --git a/libs/nitro/aws/sdk.go b/libs/nitro/aws/sdk.go index 69fc7d313..8d3c71f05 100644 --- a/libs/nitro/aws/sdk.go +++ b/libs/nitro/aws/sdk.go @@ -155,7 +155,7 @@ func NewAWSConfig(ctx context.Context, proxyAddr string, region string) (aws.Con }) return config.LoadDefaultConfig(context.TODO(), - config.WithHTTPClient(&client), + config.WithHTTPClient(client), config.WithRegion(region), config.WithCredentialsProvider(provider), config.WithLogger(applicationLogger), diff --git a/libs/nitro/mocking.go b/libs/nitro/mocking.go new file mode 100644 index 000000000..00b7110e5 --- /dev/null +++ b/libs/nitro/mocking.go @@ -0,0 +1,11 @@ +package nitro + +var enclaveMocking bool + +func MockEnclave() { + enclaveMocking = true +} + +func EnclaveMocking() bool { + return enclaveMocking +} diff --git a/nitro-shim/scripts/start-proxies.sh b/nitro-shim/scripts/start-proxies.sh index 7383e0fa3..219e766a3 100755 --- a/nitro-shim/scripts/start-proxies.sh +++ b/nitro-shim/scripts/start-proxies.sh @@ -9,8 +9,8 @@ echo "cid is ${CID}" # it's now time to set up proxy tools if [ "${service}" = "/payments" ]; then # setup inbound traffic proxy - export IN_ADDRS=":8080" - export OUT_ADDRS="${CID}:8080" + export IN_ADDRS=":8080,:8443" + export OUT_ADDRS="${CID}:8080,${CID}:8443" echo "${IN_ADDRS} to ${OUT_ADDRS}" # next startup the proxy /enclave/viproxy > /tmp/viproxy.log & diff --git a/services/cmd/serve.go b/services/cmd/serve.go index 9007f7d4f..7f4760b5d 100644 --- a/services/cmd/serve.go +++ b/services/cmd/serve.go @@ -28,9 +28,12 @@ func init() { // address - sets the address of the server to be started ServeCmd.PersistentFlags().String("address", ":8080", - "the default address to bind to") + "the address to bind to the HTTP server") + ServeCmd.PersistentFlags().String("address2", ":8443", + "the address to bind the HTTPS server") cmdutils.Must(viper.BindPFlag("address", ServeCmd.PersistentFlags().Lookup("address"))) cmdutils.Must(viper.BindEnv("address", "ADDR")) + cmdutils.Must(viper.BindEnv("address2", "ADDR2")) ServeCmd.PersistentFlags().Bool("enable-job-workers", true, "enable job workers (defaults true)") @@ -81,6 +84,7 @@ func SetupRouter(ctx context.Context) *chi.Mux { Str("build_time", ctx.Value(appctx.BuildTimeCTXKey).(string)). Str("ratios_service", viper.GetString("ratios-service")). Str("address", viper.GetString("address")). + Str("address2", viper.GetString("address2")). Str("environment", viper.GetString("environment")). Msg("server starting") } diff --git a/services/nitro/nitro.go b/services/nitro/nitro.go index aa7996645..9a924e54e 100644 --- a/services/nitro/nitro.go +++ b/services/nitro/nitro.go @@ -2,7 +2,13 @@ package nitro import ( "context" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" "fmt" + "math/big" "net/http" "runtime/debug" "strconv" @@ -157,27 +163,83 @@ func RunNitroServerInEnclave(cmd *cobra.Command, args []string) error { logger.Info().Msg("payments routes setup") // setup listener - listenAddress := viper.GetString("address") + httpListenAddress := viper.GetString("address") + + httpsListenAddress := viper.GetString("address2") // setup vsock listener - httpListener, err := nitro.Listen(ctx, listenAddress) + httpListener, err := nitro.Listen(ctx, httpListenAddress) + if err != nil { + logger.Panic().Err(err).Msg("listening on vsock port failed") + } + httpsListener, err := nitro.Listen(ctx, httpsListenAddress) if err != nil { logger.Panic().Err(err).Msg("listening on vsock port failed") } logger.Info().Msg("vsock listener setup") + tlsCertificate, err := createSelfSignedCertificate() + if err != nil { + logger.Panic().Err(err).Msg("failed to create a self-signed certoificate") + } + // setup server srv := http.Server{ Handler: chi.ServerBaseContext(ctx, r), ReadTimeout: 3 * time.Second, WriteTimeout: 20 * time.Second, } + srv.TLSConfig.Certificates = []tls.Certificate{tlsCertificate} + logger.Info().Msg("starting server") - // run the server in another routine - logger.Fatal().Err(srv.Serve(httpListener)).Msg("server shutdown") + + errChan := make(chan error, 2) + go func() { + errChan <- srv.Serve(httpListener) + }() + go func() { + errChan <- srv.ServeTLS(httpsListener, "", "") + }() + err = <-errChan + logger.Fatal().Err(err).Msg("server shutdown") return nil } +func createSelfSignedCertificate() (tls.Certificate, error) { + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return tls.Certificate{}, err + } + keyUsage := x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment + timeNow := time.Now() + + // Allow the client clock to be off by 1 min + notBefore := timeNow.Add(-time.Minute) + notAfter := timeNow.AddDate(10, 0, 0) + serialNumber := big.NewInt(1) + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Brave Software"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + template.DNSNames = []string{"nitro.localdomain"} + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, privateKey.PublicKey, privateKey) + if err != nil { + return tls.Certificate{}, err + } + return tls.Certificate{ + Certificate: [][]byte{derBytes}, + PrivateKey: privateKey, + }, nil +} + // RunNitroServerOutsideEnclave - start up all the services which are outside func RunNitroServerOutsideEnclave(cmd *cobra.Command, args []string) error { ctx := cmd.Context() diff --git a/services/payments/service.go b/services/payments/service.go index cc26ac7b8..d79b8f9cd 100644 --- a/services/payments/service.go +++ b/services/payments/service.go @@ -222,29 +222,32 @@ func NewService(ctx context.Context) (context.Context, *Service, error) { return nil, nil, errors.New("no egress addr for payments service") } - pcrs, err := nitro.GetPCRs() - if err != nil { - logger.Fatal().Err(err).Msg("could not retrieve nitro PCRs") - return nil, nil, errors.New("could not retrieve nitro PCRs") - } - store, err := NewVerifierStore() - if err != nil { - logger.Fatal().Err(err).Msg("could not create verifier store") - return nil, nil, errors.New("could not create verifier store") - } - service := &Service{ - baseCtx: ctx, - awsCfg: awsCfg, - publicKey: hex.EncodeToString(pcrs[2]), - signer: nitro.Signer{}, - verifierStore: store, - egressAddr: egressAddr, + baseCtx: ctx, + awsCfg: awsCfg, + signer: nitro.Signer{}, + egressAddr: egressAddr, } - // create the kms encryption key for this service for bootstrap operator shares - if err := service.configureKMSEncryptionKey(ctx); err != nil { - return nil, nil, fmt.Errorf("could not create kms secret encryption key: %w", err) + if !nitro.EnclaveMocking() { + pcrs, err := nitro.GetPCRs() + if err != nil { + logger.Fatal().Err(err).Msg("could not retrieve nitro PCRs") + return nil, nil, errors.New("could not retrieve nitro PCRs") + } + service.publicKey = hex.EncodeToString(pcrs[2]) + + verifierStore, err := NewVerifierStore() + if err != nil { + logger.Fatal().Err(err).Msg("could not create verifier store") + return nil, nil, errors.New("could not create verifier store") + } + service.verifierStore = verifierStore + + // create the kms encryption key for this service for bootstrap operator shares + if err := service.configureKMSEncryptionKey(ctx); err != nil { + return nil, nil, fmt.Errorf("could not create kms secret encryption key: %w", err) + } } go func() {