router.go 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package router
  2. import (
  3. "github.com/go-chi/chi/v5"
  4. "github.com/porter-dev/porter/api/server/router/middleware"
  5. "github.com/porter-dev/porter/provisioner/server/authn"
  6. "github.com/porter-dev/porter/provisioner/server/authz"
  7. "github.com/porter-dev/porter/provisioner/server/config"
  8. "github.com/porter-dev/porter/provisioner/server/handlers/credentials"
  9. "github.com/porter-dev/porter/provisioner/server/handlers/healthcheck"
  10. "github.com/porter-dev/porter/provisioner/server/handlers/provision"
  11. "github.com/porter-dev/porter/provisioner/server/handlers/state"
  12. )
  13. func NewAPIRouter(config *config.Config) *chi.Mux {
  14. r := chi.NewRouter()
  15. r.Route("/api/v1", func(r chi.Router) {
  16. // set the content type for all API endpoints and log all request info
  17. r.Use(middleware.ContentTypeJSON)
  18. // create new group for raw state endpoints which use workspace authz middleware
  19. basicAuth := authn.NewAuthNBasicFactory(config)
  20. staticTokenAuth := authn.NewAuthNStaticFactory(config)
  21. porterTokenAuth := authn.NewAuthNPorterTokenFactory(config)
  22. workspaceAuth := authz.NewWorkspaceScopedFactory(config)
  23. r.Method("GET", "/readyz", healthcheck.NewReadyzHandler(config))
  24. r.Method("GET", "/livez", healthcheck.NewLivezHandler(config))
  25. r.Group(func(r chi.Router) {
  26. // This group is meant to be called via a provisioner pod
  27. r.Group(func(r chi.Router) {
  28. r.Use(porterTokenAuth.NewAuthenticated)
  29. r.Use(workspaceAuth.Middleware)
  30. r.Method("POST", "/{workspace_id}/resource", state.NewCreateResourceHandler(config))
  31. r.Method("DELETE", "/{workspace_id}/resource", state.NewDeleteResourceHandler(config))
  32. r.Method("POST", "/{workspace_id}/error", state.NewReportErrorHandler(config))
  33. r.Method("GET", "/{workspace_id}/credentials", credentials.NewCredentialsGetHandler(config))
  34. })
  35. // This group is meant to be called from Terraform via basic auth
  36. r.Group(func(r chi.Router) {
  37. r.Use(basicAuth.NewAuthenticated)
  38. r.Use(workspaceAuth.Middleware)
  39. r.Method("GET", "/{workspace_id}/tfstate", state.NewRawStateGetHandler(config))
  40. r.Method("POST", "/{workspace_id}/tfstate", state.NewRawStateUpdateHandler(config))
  41. })
  42. // This group is meant to be called via the API server
  43. r.Group(func(r chi.Router) {
  44. r.Use(staticTokenAuth.NewAuthenticated)
  45. r.Use(workspaceAuth.Middleware)
  46. // Note that this handler is also used in the above group. The /tfstate/raw endpoint is meant to
  47. // be used from the API server, while the /tfstate endpoint is meant to be called as a Terraform
  48. // HTTP backend.
  49. r.Method("GET", "/{workspace_id}/tfstate/raw", state.NewRawStateGetHandler(config))
  50. r.Method("GET", "/{workspace_id}/logs", state.NewLogsGetHandler(config))
  51. })
  52. })
  53. // use project and infra-scoped middleware
  54. projectAuth := authz.NewProjectScopedFactory(config)
  55. infraAuth := authz.NewInfraScopedFactory(config)
  56. // This group is meant to be called via the API server
  57. r.Group(func(r chi.Router) {
  58. r.Use(staticTokenAuth.NewAuthenticated)
  59. r.Use(projectAuth.Middleware)
  60. r.Use(infraAuth.Middleware)
  61. r.Method("GET", "/projects/{project_id}/infras/{infra_id}/state", state.NewStateGetHandler(config))
  62. r.Method("POST", "/projects/{project_id}/infras/{infra_id}/apply", provision.NewProvisionApplyHandler(config))
  63. r.Method("DELETE", "/projects/{project_id}/infras/{infra_id}", provision.NewProvisionDestroyHandler(config))
  64. })
  65. })
  66. return r
  67. }