cluster.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package authz
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "github.com/porter-dev/porter/api/server/authz/policy"
  7. "github.com/porter-dev/porter/api/server/shared"
  8. "github.com/porter-dev/porter/api/server/shared/apierrors"
  9. "github.com/porter-dev/porter/api/types"
  10. "github.com/porter-dev/porter/internal/kubernetes"
  11. "github.com/porter-dev/porter/internal/models"
  12. )
  13. const KubernetesAgentCtxKey string = "k8s-agent"
  14. const HelmAgentCtxKey string = "helm-agent"
  15. type ClusterScopedFactory struct {
  16. config *shared.Config
  17. }
  18. func NewClusterScopedFactory(
  19. config *shared.Config,
  20. ) *ClusterScopedFactory {
  21. return &ClusterScopedFactory{config}
  22. }
  23. func (p *ClusterScopedFactory) Middleware(next http.Handler) http.Handler {
  24. return &ClusterScopedMiddleware{next, p.config}
  25. }
  26. type ClusterScopedMiddleware struct {
  27. next http.Handler
  28. config *shared.Config
  29. }
  30. func (p *ClusterScopedMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  31. // get the project id from the URL param context
  32. reqScopes, _ := r.Context().Value(RequestScopeCtxKey).(map[types.PermissionScope]*policy.RequestAction)
  33. clusterID := reqScopes[types.ClusterScope].Resource.UInt
  34. cluster, err := p.config.Repo.Cluster().ReadCluster(clusterID)
  35. if err != nil {
  36. apierrors.HandleAPIError(w, p.config.Logger, apierrors.NewErrInternal(err))
  37. return
  38. }
  39. ctx := NewClusterContext(r.Context(), cluster)
  40. r = r.WithContext(ctx)
  41. p.next.ServeHTTP(w, r)
  42. }
  43. func NewClusterContext(ctx context.Context, cluster *models.Cluster) context.Context {
  44. return context.WithValue(ctx, types.ClusterScope, cluster)
  45. }
  46. type KubernetesAgentGetter interface {
  47. GetOutOfClusterConfig(cluster *models.Cluster) *kubernetes.OutOfClusterConfig
  48. GetAgent(r *http.Request, cluster *models.Cluster) (*kubernetes.Agent, error)
  49. }
  50. type OutOfClusterAgentGetter struct {
  51. config *shared.Config
  52. }
  53. func NewOutOfClusterAgentGetter(config *shared.Config) KubernetesAgentGetter {
  54. return &OutOfClusterAgentGetter{config}
  55. }
  56. func (d *OutOfClusterAgentGetter) GetOutOfClusterConfig(cluster *models.Cluster) *kubernetes.OutOfClusterConfig {
  57. return &kubernetes.OutOfClusterConfig{
  58. Repo: d.config.Repo,
  59. DigitalOceanOAuth: d.config.DOConf,
  60. Cluster: cluster,
  61. }
  62. }
  63. func (d *OutOfClusterAgentGetter) GetAgent(r *http.Request, cluster *models.Cluster) (*kubernetes.Agent, error) {
  64. // look for the agent in context
  65. ctxAgentVal := r.Context().Value(types.ClusterScope)
  66. if ctxAgentVal != nil {
  67. if agent, ok := ctxAgentVal.(*kubernetes.Agent); ok {
  68. return agent, nil
  69. }
  70. }
  71. // if agent not found in context, get the agent from out of cluster config
  72. ooc := d.GetOutOfClusterConfig(cluster)
  73. agent, err := kubernetes.GetAgentOutOfClusterConfig(ooc)
  74. if err != nil {
  75. return nil, fmt.Errorf("failed to get agent: %s", err.Error())
  76. }
  77. newCtx := context.WithValue(r.Context(), KubernetesAgentCtxKey, agent)
  78. r = r.WithContext(newCtx)
  79. return agent, nil
  80. }