| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package authmanagement
- import (
- "context"
- "fmt"
- "net/http"
- "time"
- grpcreflect "github.com/bufbuild/connect-grpcreflect-go"
- "github.com/porter-dev/porter/ee/integrations/vault"
- "github.com/porter-dev/porter/internal/repository/credentials"
- "github.com/porter-dev/porter/internal/repository/gorm"
- "github.com/porter-dev/porter/api/server/shared/config/env"
- "github.com/porter-dev/porter/internal/adapter"
- "github.com/porter-dev/porter/internal/repository"
- "github.com/joeshaw/envdecode"
- "github.com/bufbuild/connect-go"
- otelconnect "github.com/bufbuild/connect-opentelemetry-go"
- "github.com/porter-dev/api-contracts/generated/go/porter/v1/porterv1connect"
- "golang.org/x/net/http2"
- "golang.org/x/net/http2/h2c"
- )
- // ServiceEnv contains all environment variables for the AuthManagementService
- type ServiceEnv struct {
- // Port is the port that the AuthManagementService listens on
- Port int `env:"AUTH_MANAGEMENT_SERVICE_PORT,default=8090"`
- // TokenGeneratorSecret is the secret used to generate JWT tokens
- TokenGeneratorSecret string `env:"TOKEN_GENERATOR_SECRET,default=secret"`
- }
- // EnvVars holds all the environment variables to be decoded for the AuthManagementService
- type EnvVars struct {
- // DBEnv holds all the environment variables for DB connection
- DBEnv env.DBConf
- // ServiceEnv holds all the environment variables specific to the AuthManagementService
- ServiceEnv ServiceEnv
- }
- // Config contains all configuration options for the AuthManagementService
- type Config struct {
- // Port is the port that the AuthManagementService listens on
- Port int
- // TokenGeneratorSecret is the secret used to generate JWT tokens
- TokenGeneratorSecret string
- // APITokenManager is the interface for managing API tokens
- APITokenManager repository.APITokenRepository
- }
- // AuthManagementService stores the service config and implements the gRPC server's interface
- type AuthManagementService struct {
- Config Config
- }
- // NewService loads the authmanagement.Config from the environment and returns an initialized AuthManagementService
- func NewService() (AuthManagementService, error) {
- var server AuthManagementService
- var envVars EnvVars
- if err := envdecode.StrictDecode(&envVars); err != nil {
- return server, fmt.Errorf("failed to decode environment variables: %w", err)
- }
- db, err := adapter.New(&envVars.DBEnv)
- if err != nil {
- return server, fmt.Errorf("failed to create DB client: %w", err)
- }
- var instanceCredentialBackend credentials.CredentialStorage
- if envVars.DBEnv.VaultEnabled {
- instanceCredentialBackend = vault.NewClient(
- envVars.DBEnv.VaultServerURL,
- envVars.DBEnv.VaultAPIKey,
- envVars.DBEnv.VaultPrefix,
- )
- }
- var key [32]byte
- for i, b := range []byte(envVars.DBEnv.EncryptionKey) {
- key[i] = b
- }
- repo := gorm.NewRepository(db, &key, instanceCredentialBackend)
- server.Config = Config{
- Port: envVars.ServiceEnv.Port,
- TokenGeneratorSecret: envVars.ServiceEnv.TokenGeneratorSecret,
- APITokenManager: repo.APIToken(),
- }
- return server, nil
- }
- // ListenAndServe starts the AuthManagementService and will shutdown when the context is canceled
- func (a AuthManagementService) ListenAndServe(ctx context.Context) error {
- ctx, cancel := context.WithCancel(ctx)
- defer cancel()
- mux := http.NewServeMux()
- reflector := grpcreflect.NewStaticReflector(
- "porter.v1.AuthManagementService",
- )
- mux.Handle(grpcreflect.NewHandlerV1(reflector))
- mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector))
- mux.Handle(porterv1connect.NewAuthManagementServiceHandler(a,
- connect.WithInterceptors(
- otelconnect.NewInterceptor(otelconnect.WithTrustRemote()),
- ),
- ))
- srv := &http.Server{
- Addr: fmt.Sprintf("0.0.0.0:%d", a.Config.Port),
- ReadTimeout: 5 * time.Second,
- // TODO: remove this. Use h2c so we can serve HTTP/2 without TLS.
- Handler: h2c.NewHandler(mux, &http2.Server{}),
- }
- defer srv.Shutdown(ctx) // nolint:errcheck
- errChan := make(chan error)
- go func() {
- err := srv.ListenAndServe()
- if err != nil {
- errChan <- err
- }
- }()
- select {
- case err := <-errChan:
- return err
- case <-ctx.Done():
- }
- return nil
- }
|