2023-09-27 05:40:32 -04:00
/ *
Copyright ( c ) Edgeless Systems GmbH
SPDX - License - Identifier : AGPL - 3.0 - only
* /
/ *
Package main parses command line flags and starts the s3proxy server .
* /
package main
import (
"crypto/tls"
"flag"
"fmt"
2024-02-08 09:20:01 -05:00
"log/slog"
2023-09-27 05:40:32 -04:00
"net"
"net/http"
"github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/s3proxy/internal/router"
)
const (
// defaultPort is the default port to listen on.
defaultPort = 4433
// defaultIP is the default IP to listen on.
defaultIP = "0.0.0.0"
// defaultRegion is the default AWS region to use.
defaultRegion = "eu-west-1"
// defaultCertLocation is the default location of the TLS certificate.
defaultCertLocation = "/etc/s3proxy/certs"
// defaultLogLevel is the default log level.
defaultLogLevel = 0
)
func main ( ) {
flags , err := parseFlags ( )
if err != nil {
panic ( err )
}
// logLevel can be made a public variable so logging level can be changed dynamically.
// TODO (derpsteb): enable once we are on go 1.21.
// logLevel := new(slog.LevelVar)
2024-02-08 09:20:01 -05:00
// handler := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: logLevel})
2023-09-27 05:40:32 -04:00
// logger := slog.New(handler)
// logLevel.Set(flags.logLevel)
2024-02-08 09:20:01 -05:00
logger := logger . NewJSONLogger ( logger . VerbosityFromInt ( flags . logLevel ) )
2023-09-27 05:40:32 -04:00
2023-10-09 09:18:12 -04:00
if flags . forwardMultipartReqs {
2024-02-08 09:20:01 -05:00
logger . Warn ( "configured to forward multipart uploads, this may leak data to AWS" )
2023-10-09 09:18:12 -04:00
}
2023-09-27 05:40:32 -04:00
if err := runServer ( flags , logger ) ; err != nil {
panic ( err )
}
}
2024-02-08 09:20:01 -05:00
func runServer ( flags cmdFlags , log * slog . Logger ) error {
log . With ( slog . String ( "ip" , flags . ip ) , slog . Int ( "port" , defaultPort ) , slog . String ( "region" , flags . region ) ) . Info ( "listening" )
2023-09-27 05:40:32 -04:00
2023-10-09 09:18:12 -04:00
router , err := router . New ( flags . region , flags . kmsEndpoint , flags . forwardMultipartReqs , log )
2023-10-02 03:00:38 -04:00
if err != nil {
return fmt . Errorf ( "creating router: %w" , err )
}
2023-09-27 05:40:32 -04:00
server := http . Server {
Addr : fmt . Sprintf ( "%s:%d" , flags . ip , defaultPort ) ,
Handler : http . HandlerFunc ( router . Serve ) ,
// Disable HTTP/2. Serving HTTP/2 will cause some clients to use HTTP/2.
// It seems like AWS S3 does not support HTTP/2.
// Having HTTP/2 enabled will at least cause the aws-sdk-go V1 copy-object operation to fail.
TLSNextProto : map [ string ] func ( * http . Server , * tls . Conn , http . Handler ) { } ,
}
// i.e. if TLS is enabled.
if ! flags . noTLS {
cert , err := tls . LoadX509KeyPair ( flags . certLocation + "/s3proxy.crt" , flags . certLocation + "/s3proxy.key" )
if err != nil {
return fmt . Errorf ( "loading TLS certificate: %w" , err )
}
server . TLSConfig = & tls . Config {
Certificates : [ ] tls . Certificate { cert } ,
}
// TLSConfig is populated, so we can safely pass empty strings to ListenAndServeTLS.
return server . ListenAndServeTLS ( "" , "" )
}
2024-02-08 09:20:01 -05:00
log . Warn ( "TLS is disabled" )
2023-09-27 05:40:32 -04:00
return server . ListenAndServe ( )
}
func parseFlags ( ) ( cmdFlags , error ) {
noTLS := flag . Bool ( "no-tls" , false , "disable TLS and listen on port 80, otherwise listen on 443" )
ip := flag . String ( "ip" , defaultIP , "ip to listen on" )
region := flag . String ( "region" , defaultRegion , "AWS region in which target bucket is located" )
certLocation := flag . String ( "cert" , defaultCertLocation , "location of TLS certificate" )
2023-10-02 03:00:38 -04:00
kmsEndpoint := flag . String ( "kms" , "key-service.kube-system:9000" , "endpoint of the KMS service to get key encryption keys from" )
2023-10-09 09:18:12 -04:00
forwardMultipartReqs := flag . Bool ( "allow-multipart" , false , "forward multipart requests to the target bucket; beware: this may store unencrypted data on AWS. See the documentation for more information" )
2023-09-27 05:40:32 -04:00
level := flag . Int ( "level" , defaultLogLevel , "log level" )
flag . Parse ( )
netIP := net . ParseIP ( * ip )
if netIP == nil {
return cmdFlags { } , fmt . Errorf ( "not a valid IPv4 address: %s" , * ip )
}
// TODO(derpsteb): enable once we are on go 1.21.
// logLevel := new(slog.Level)
// if err := logLevel.UnmarshalText([]byte(*level)); err != nil {
// return cmdFlags{}, fmt.Errorf("parsing log level: %w", err)
// }
2023-10-02 03:00:38 -04:00
return cmdFlags {
2023-10-09 09:18:12 -04:00
noTLS : * noTLS ,
ip : netIP . String ( ) ,
region : * region ,
certLocation : * certLocation ,
kmsEndpoint : * kmsEndpoint ,
forwardMultipartReqs : * forwardMultipartReqs ,
logLevel : * level ,
2023-10-02 03:00:38 -04:00
} , nil
2023-09-27 05:40:32 -04:00
}
type cmdFlags struct {
2023-10-09 09:18:12 -04:00
noTLS bool
ip string
region string
certLocation string
kmsEndpoint string
forwardMultipartReqs bool
2023-09-27 05:40:32 -04:00
// TODO(derpsteb): enable once we are on go 1.21.
// logLevel slog.Level
logLevel int
}