package service import ( "context" "fmt" "net" "os" "esxlib/api/cloud" "esxlib/esx" "esxlib/pkg/utils" "git.twelvetwelve.org/library/core/log" "github.com/madflojo/testcerts" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) type CloudServer struct { cloud.UnimplementedCloudServer esx map[string]*esx.Client config *Config } var authorizedTokens = map[string]string{} func unaryInterceptor(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { // Auth is not enabled on the server if len(authorizedTokens) == 0 { return handler(ctx, req) } md, ok := metadata.FromIncomingContext(ctx) if !ok { log.Debugf("no metadata\n") return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated access") } values := md["authorization"] if len(values) == 0 { log.Debugf("no authorization %+v\n", values) return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated access") } for _, v := range values { if _, ok := authorizedTokens[v]; ok { return handler(ctx, req) } } log.Debugf("no authorization %+v\n", md) return nil, status.Errorf(codes.Unauthenticated, "Unauthenticated access") } func Run(configFile string) error { config := &Config{} if err := utils.UnmarshalFromFile(configFile, config); err != nil { return err } esxClients := make(map[string]*esx.Client) for k := range config.Zones { zone, _ := config.Zones[k] client, err := esx.NewClientFromConfig(&zone) if err != nil { return err } esxClients[k] = client } lis, err := net.Listen("tcp", config.ListenAddress) if err != nil { panic(err) } // TLS: Generate TLS if not provided if config.TLS.CertPath == "" && config.TLS.KeyPath == "" { config.TLS.CertPath, config.TLS.KeyPath, err = testcerts.GenerateCertsToTempFile("/tmp/") if err != nil { return err } fmt.Printf("Creating credentials... %s:%s\n", config.TLS.CertPath, config.TLS.KeyPath) defer os.Remove(config.TLS.CertPath) defer os.Remove(config.TLS.KeyPath) } // generate local certs creds, err := credentials.NewServerTLSFromFile(config.TLS.CertPath, config.TLS.KeyPath) if err != nil { log.Fatalf("Failed to setup TLS: %v\n", err) } var grpcServer *grpc.Server if config.Token != "" { fmt.Printf("Need token: %s\n", config.Token) authorizedTokens[config.Token] = config.Token grpcServer = grpc.NewServer(grpc.Creds(creds), grpc.UnaryInterceptor(unaryInterceptor)) } else { grpcServer = grpc.NewServer(grpc.Creds(creds)) } cloudServer := CloudServer{ esx: esxClients, config: config, } cloud.RegisterCloudServer(grpcServer, &cloudServer) log.Printf("server listening at %v\n", lis.Addr()) if err := grpcServer.Serve(lis); err != nil { return err } return nil }