create_integration.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. package saml
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "net/url"
  7. "strings"
  8. "github.com/porter-dev/porter/api/server/handlers"
  9. "github.com/porter-dev/porter/api/server/shared"
  10. "github.com/porter-dev/porter/api/server/shared/apierrors"
  11. "github.com/porter-dev/porter/api/server/shared/config"
  12. "github.com/porter-dev/porter/api/types"
  13. "github.com/porter-dev/porter/internal/models"
  14. "github.com/porter-dev/porter/internal/models/saml"
  15. "gorm.io/gorm"
  16. )
  17. type CreateSAMLIntegrationHandler struct {
  18. handlers.PorterHandlerReadWriter
  19. }
  20. func NewCreateSAMLIntegrationHandler(
  21. config *config.Config,
  22. decoderValidator shared.RequestDecoderValidator,
  23. writer shared.ResultWriter,
  24. ) *CreateSAMLIntegrationHandler {
  25. return &CreateSAMLIntegrationHandler{
  26. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  27. }
  28. }
  29. func (h *CreateSAMLIntegrationHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  30. project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  31. if !project.SAMLSSOEnabled {
  32. h.HandleAPIError(w, r, apierrors.NewErrForbidden(errors.New("SAML SSO is not enabled for this project")))
  33. return
  34. }
  35. // FIXME: check if user has necessary permissions to make this request with RBAC
  36. request := &types.CreateSAMLIntegrationRequest{}
  37. if ok := h.DecodeAndValidate(w, r, request); !ok {
  38. return
  39. }
  40. for _, domain := range request.Domains {
  41. parsed, err := url.Parse("https://" + domain)
  42. if err != nil || parsed.Host != domain {
  43. h.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(fmt.Errorf("invalid domain %s", domain),
  44. http.StatusBadRequest))
  45. return
  46. }
  47. _, err = h.Repo().SAMLIntegration().ValidateSAMLIntegration(domain)
  48. if err == nil {
  49. h.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
  50. fmt.Errorf("domain %s already exists in another SAML integration, please talk to the Porter team for help",
  51. domain), http.StatusBadRequest))
  52. return
  53. } else if !errors.Is(err, gorm.ErrRecordNotFound) {
  54. h.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  55. return
  56. }
  57. }
  58. integ := &saml.SAMLIntegration{
  59. ProjectID: project.ID,
  60. Domains: strings.Join(request.Domains, ","),
  61. SignOnURL: request.SignOnURL,
  62. CertificateData: []byte(request.CertificateData),
  63. }
  64. if _, err := h.Repo().SAMLIntegration().CreateSAMLIntegration(integ); err != nil {
  65. h.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  66. return
  67. }
  68. }