get_credentials_ee.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // +build ee
  2. package credentials
  3. import (
  4. "fmt"
  5. "net/http"
  6. "github.com/porter-dev/porter/api/server/shared"
  7. "github.com/porter-dev/porter/api/server/shared/apierrors"
  8. "github.com/porter-dev/porter/ee/api/types"
  9. "github.com/porter-dev/porter/ee/integrations/vault"
  10. "github.com/porter-dev/porter/internal/models"
  11. "github.com/porter-dev/porter/internal/repository/credentials"
  12. "github.com/porter-dev/porter/internal/repository/gorm"
  13. "golang.org/x/crypto/bcrypt"
  14. "github.com/porter-dev/porter/provisioner/server/config"
  15. )
  16. type CredentialsGetHandler struct {
  17. config *config.Config
  18. resultWriter shared.ResultWriter
  19. }
  20. func NewCredentialsGetHandler(
  21. config *config.Config,
  22. ) http.Handler {
  23. return &CredentialsGetHandler{
  24. config: config,
  25. resultWriter: shared.NewDefaultResultWriter(config.Logger, config.Alerter),
  26. }
  27. }
  28. func (c *CredentialsGetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  29. ceToken, _ := r.Context().Value("ce_token").(*models.CredentialsExchangeToken)
  30. // read the request to get the token id and hashed token
  31. req := &types.CredentialsExchangeRequest{}
  32. req.VaultToken = r.Header.Get("X-Vault-Token")
  33. resp := &types.CredentialsExchangeResponse{}
  34. repo := c.config.Repo
  35. // if the request contains a vault token, use that vault token to construct a new repository
  36. // that will query vault using the passed in token
  37. if req.VaultToken != "" {
  38. // read the vault token in the header, create new vault client with this token
  39. conf := c.config.DBConf
  40. vaultClient := vault.NewClient(conf.VaultServerURL, req.VaultToken, conf.VaultPrefix)
  41. var key [32]byte
  42. for i, b := range []byte(conf.EncryptionKey) {
  43. key[i] = b
  44. }
  45. // use this vault client for the repo
  46. repo = gorm.NewRepository(c.config.DB, &key, vaultClient)
  47. }
  48. if ceToken.DOCredentialID != 0 {
  49. doInt, err := repo.OAuthIntegration().ReadOAuthIntegration(ceToken.ProjectID, ceToken.DOCredentialID)
  50. if err != nil {
  51. apierrors.HandleAPIError(c.config.Logger, c.config.Alerter, w, r, apierrors.NewErrForbidden(err), true)
  52. return
  53. }
  54. resp.DO = &credentials.OAuthCredential{
  55. ClientID: doInt.ClientID,
  56. AccessToken: doInt.AccessToken,
  57. RefreshToken: doInt.RefreshToken,
  58. }
  59. } else if ceToken.GCPCredentialID != 0 {
  60. gcpInt, err := repo.GCPIntegration().ReadGCPIntegration(ceToken.ProjectID, ceToken.GCPCredentialID)
  61. if err != nil {
  62. apierrors.HandleAPIError(c.config.Logger, c.config.Alerter, w, r, apierrors.NewErrForbidden(err), true)
  63. return
  64. }
  65. resp.GCP = &credentials.GCPCredential{
  66. GCPKeyData: gcpInt.GCPKeyData,
  67. GCPProjectID: []byte(gcpInt.GCPProjectID),
  68. }
  69. } else if ceToken.AWSCredentialID != 0 {
  70. awsInt, err := repo.AWSIntegration().ReadAWSIntegration(ceToken.ProjectID, ceToken.AWSCredentialID)
  71. if err != nil {
  72. apierrors.HandleAPIError(c.config.Logger, c.config.Alerter, w, r, apierrors.NewErrForbidden(err), true)
  73. return
  74. }
  75. resp.AWS = &credentials.AWSCredential{
  76. AWSAccessKeyID: awsInt.AWSAccessKeyID,
  77. AWSClusterID: awsInt.AWSClusterID,
  78. AWSSecretAccessKey: awsInt.AWSSecretAccessKey,
  79. AWSSessionToken: awsInt.AWSSessionToken,
  80. AWSRegion: []byte(awsInt.AWSRegion),
  81. }
  82. } else if ceToken.AzureCredentialID != 0 {
  83. azInt, err := repo.AzureIntegration().ReadAzureIntegration(ceToken.ProjectID, ceToken.AzureCredentialID)
  84. if err != nil {
  85. apierrors.HandleAPIError(c.config.Logger, c.config.Alerter, w, r, apierrors.NewErrForbidden(err), true)
  86. return
  87. }
  88. resp.Azure = &credentials.AzureCredential{
  89. SubscriptionID: azInt.AzureSubscriptionID,
  90. TenantID: azInt.AzureTenantID,
  91. ClientID: azInt.AzureClientID,
  92. ServicePrincipalSecret: azInt.ServicePrincipalSecret,
  93. }
  94. }
  95. // return the decrypted credentials
  96. c.resultWriter.WriteResult(w, r, resp)
  97. }
  98. func verifyToken(reqToken string, ceToken *models.CredentialsExchangeToken) (bool, error) {
  99. // make sure the token is still valid and has not expired
  100. if ceToken.IsExpired() {
  101. return false, fmt.Errorf("token is expired")
  102. }
  103. // make sure the token is correct
  104. if err := bcrypt.CompareHashAndPassword([]byte(ceToken.Token), []byte(reqToken)); err != nil {
  105. return false, fmt.Errorf("verify token failed: %s", err)
  106. }
  107. return true, nil
  108. }