server.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package authmanagement
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "time"
  7. grpcreflect "github.com/bufbuild/connect-grpcreflect-go"
  8. "github.com/porter-dev/porter/ee/integrations/vault"
  9. "github.com/porter-dev/porter/internal/repository/credentials"
  10. "github.com/porter-dev/porter/internal/repository/gorm"
  11. "github.com/porter-dev/porter/api/server/shared/config/env"
  12. "github.com/porter-dev/porter/internal/adapter"
  13. "github.com/porter-dev/porter/internal/repository"
  14. "github.com/joeshaw/envdecode"
  15. "github.com/bufbuild/connect-go"
  16. otelconnect "github.com/bufbuild/connect-opentelemetry-go"
  17. "github.com/porter-dev/api-contracts/generated/go/porter/v1/porterv1connect"
  18. "golang.org/x/net/http2"
  19. "golang.org/x/net/http2/h2c"
  20. )
  21. // ServiceEnv contains all environment variables for the AuthManagementService
  22. type ServiceEnv struct {
  23. // Port is the port that the AuthManagementService listens on
  24. Port int `env:"AUTH_MANAGEMENT_SERVICE_PORT,default=8090"`
  25. // TokenGeneratorSecret is the secret used to generate JWT tokens
  26. TokenGeneratorSecret string `env:"TOKEN_GENERATOR_SECRET,default=secret"`
  27. }
  28. // EnvVars holds all the environment variables to be decoded for the AuthManagementService
  29. type EnvVars struct {
  30. // DBEnv holds all the environment variables for DB connection
  31. DBEnv env.DBConf
  32. // ServiceEnv holds all the environment variables specific to the AuthManagementService
  33. ServiceEnv ServiceEnv
  34. }
  35. // Config contains all configuration options for the AuthManagementService
  36. type Config struct {
  37. // Port is the port that the AuthManagementService listens on
  38. Port int
  39. // TokenGeneratorSecret is the secret used to generate JWT tokens
  40. TokenGeneratorSecret string
  41. // APITokenManager is the interface for managing API tokens
  42. APITokenManager repository.APITokenRepository
  43. }
  44. // AuthManagementService stores the service config and implements the gRPC server's interface
  45. type AuthManagementService struct {
  46. Config Config
  47. }
  48. // NewService loads the authmanagement.Config from the environment and returns an initialized AuthManagementService
  49. func NewService() (AuthManagementService, error) {
  50. var server AuthManagementService
  51. var envVars EnvVars
  52. if err := envdecode.StrictDecode(&envVars); err != nil {
  53. return server, fmt.Errorf("failed to decode environment variables: %w", err)
  54. }
  55. db, err := adapter.New(&envVars.DBEnv)
  56. if err != nil {
  57. return server, fmt.Errorf("failed to create DB client: %w", err)
  58. }
  59. var instanceCredentialBackend credentials.CredentialStorage
  60. if envVars.DBEnv.VaultEnabled {
  61. instanceCredentialBackend = vault.NewClient(
  62. envVars.DBEnv.VaultServerURL,
  63. envVars.DBEnv.VaultAPIKey,
  64. envVars.DBEnv.VaultPrefix,
  65. )
  66. }
  67. var key [32]byte
  68. for i, b := range []byte(envVars.DBEnv.EncryptionKey) {
  69. key[i] = b
  70. }
  71. repo := gorm.NewRepository(db, &key, instanceCredentialBackend)
  72. server.Config = Config{
  73. Port: envVars.ServiceEnv.Port,
  74. TokenGeneratorSecret: envVars.ServiceEnv.TokenGeneratorSecret,
  75. APITokenManager: repo.APIToken(),
  76. }
  77. return server, nil
  78. }
  79. // ListenAndServe starts the AuthManagementService and will shutdown when the context is canceled
  80. func (a AuthManagementService) ListenAndServe(ctx context.Context) error {
  81. ctx, cancel := context.WithCancel(ctx)
  82. defer cancel()
  83. mux := http.NewServeMux()
  84. reflector := grpcreflect.NewStaticReflector(
  85. "porter.v1.AuthManagementService",
  86. )
  87. mux.Handle(grpcreflect.NewHandlerV1(reflector))
  88. mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector))
  89. mux.Handle(porterv1connect.NewAuthManagementServiceHandler(a,
  90. connect.WithInterceptors(
  91. otelconnect.NewInterceptor(otelconnect.WithTrustRemote()),
  92. ),
  93. ))
  94. srv := &http.Server{
  95. Addr: fmt.Sprintf("0.0.0.0:%d", a.Config.Port),
  96. ReadTimeout: 5 * time.Second,
  97. // TODO: remove this. Use h2c so we can serve HTTP/2 without TLS.
  98. Handler: h2c.NewHandler(mux, &http2.Server{}),
  99. }
  100. defer srv.Shutdown(ctx) // nolint:errcheck
  101. errChan := make(chan error)
  102. go func() {
  103. err := srv.ListenAndServe()
  104. if err != nil {
  105. errChan <- err
  106. }
  107. }()
  108. select {
  109. case err := <-errChan:
  110. return err
  111. case <-ctx.Done():
  112. }
  113. return nil
  114. }