| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- //go:build ee
- // +build ee
- package credentials
- import (
- "fmt"
- "net/http"
- "strconv"
- "github.com/porter-dev/porter/api/server/handlers"
- "github.com/porter-dev/porter/api/server/shared"
- "github.com/porter-dev/porter/api/server/shared/apierrors"
- "github.com/porter-dev/porter/api/server/shared/config"
- "github.com/porter-dev/porter/ee/api/types"
- "github.com/porter-dev/porter/ee/integrations/vault"
- "github.com/porter-dev/porter/internal/models"
- "github.com/porter-dev/porter/internal/repository/credentials"
- "github.com/porter-dev/porter/internal/repository/gorm"
- "golang.org/x/crypto/bcrypt"
- )
- type CredentialsGetHandler struct {
- handlers.PorterHandlerReadWriter
- }
- func NewCredentialsGetHandler(
- config *config.Config,
- decoderValidator shared.RequestDecoderValidator,
- writer shared.ResultWriter,
- ) http.Handler {
- return &CredentialsGetHandler{
- PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, nil, writer),
- }
- }
- func (c *CredentialsGetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- // read the request to get the token id and hashed token
- req := &types.CredentialsExchangeRequest{}
- // populate the request from the headers
- req.CredExchangeToken = r.Header.Get("X-Porter-Token")
- tokID, err := strconv.ParseUint(r.Header.Get("X-Porter-Token-ID"), 10, 64)
- if err != nil {
- c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
- return
- }
- req.CredExchangeID = uint(tokID)
- req.VaultToken = r.Header.Get("X-Vault-Token")
- // read the access token in the header, check against DB
- ceToken, err := c.Repo().CredentialsExchangeToken().ReadCredentialsExchangeToken(req.CredExchangeID)
- if err != nil {
- c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
- return
- }
- // TODO: verify hashed token!!
- if valid, err := verifyToken(req.CredExchangeToken, ceToken); !valid {
- c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
- return
- }
- resp := &types.CredentialsExchangeResponse{}
- repo := c.Repo()
- // if the request contains a vault token, use that vault token to construct a new repository
- // that will query vault using the passed in token
- if req.VaultToken != "" {
- // read the vault token in the header, create new vault client with this token
- conf := c.Config().DBConf
- vaultClient := vault.NewClient(conf.VaultServerURL, req.VaultToken, conf.VaultPrefix)
- var key [32]byte
- for i, b := range []byte(conf.EncryptionKey) {
- key[i] = b
- }
- // use this vault client for the repo
- repo = gorm.NewRepository(c.Config().DB, &key, vaultClient)
- }
- if ceToken.DOCredentialID != 0 {
- doInt, err := repo.OAuthIntegration().ReadOAuthIntegration(ceToken.ProjectID, ceToken.DOCredentialID)
- if err != nil {
- c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
- return
- }
- resp.DO = &credentials.OAuthCredential{
- ClientID: doInt.ClientID,
- AccessToken: doInt.AccessToken,
- RefreshToken: doInt.RefreshToken,
- }
- } else if ceToken.GCPCredentialID != 0 {
- gcpInt, err := repo.GCPIntegration().ReadGCPIntegration(ceToken.ProjectID, ceToken.GCPCredentialID)
- if err != nil {
- c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
- return
- }
- resp.GCP = &credentials.GCPCredential{
- GCPKeyData: gcpInt.GCPKeyData,
- }
- } else if ceToken.AWSCredentialID != 0 {
- awsInt, err := repo.AWSIntegration().ReadAWSIntegration(ceToken.ProjectID, ceToken.AWSCredentialID)
- if err != nil {
- c.HandleAPIError(w, r, apierrors.NewErrForbidden(err))
- return
- }
- resp.AWS = &credentials.AWSCredential{
- AWSAccessKeyID: awsInt.AWSAccessKeyID,
- AWSClusterID: awsInt.AWSClusterID,
- AWSSecretAccessKey: awsInt.AWSSecretAccessKey,
- AWSSessionToken: awsInt.AWSSessionToken,
- AWSAssumeRoleArn: []byte(awsInt.AWSAssumeRoleArn),
- }
- }
- // return the decrypted credentials
- c.WriteResult(w, r, resp)
- }
- func verifyToken(reqToken string, ceToken *models.CredentialsExchangeToken) (bool, error) {
- // make sure the token is still valid and has not expired
- if ceToken.IsExpired() {
- return false, fmt.Errorf("token is expired")
- }
- // make sure the token is correct
- if err := bcrypt.CompareHashAndPassword([]byte(ceToken.Token), []byte(reqToken)); err != nil {
- return false, fmt.Errorf("verify token failed: %s", err)
- }
- return true, nil
- }
|