gateway: move secret logic from api to actions

This commit is contained in:
Simone Gotti 2019-05-05 14:11:29 +02:00
parent f73f0ba434
commit 64044df94d
3 changed files with 154 additions and 57 deletions

View File

@ -0,0 +1,119 @@
// Copyright 2019 Sorint.lab
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
// See the License for the specific language governing permissions and
// limitations under the License.
package action
import (
"context"
"net/http"
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
"github.com/sorintlab/agola/internal/services/types"
"github.com/sorintlab/agola/internal/util"
"go.uber.org/zap"
"github.com/pkg/errors"
)
type GetSecretsRequest struct {
ParentType types.ConfigType
ParentRef string
Tree bool
}
func (h *ActionHandler) GetSecrets(ctx context.Context, req *GetSecretsRequest) ([]*csapi.Secret, error) {
var cssecrets []*csapi.Secret
var resp *http.Response
var err error
switch req.ParentType {
case types.ConfigTypeProjectGroup:
cssecrets, resp, err = h.configstoreClient.GetProjectGroupSecrets(ctx, req.ParentRef, req.Tree)
case types.ConfigTypeProject:
cssecrets, resp, err = h.configstoreClient.GetProjectSecrets(ctx, req.ParentRef, req.Tree)
}
if err != nil {
return nil, ErrFromRemote(resp, err)
}
return cssecrets, nil
}
type CreateSecretRequest struct {
Name string
ParentType types.ConfigType
ParentRef string
Type types.SecretType
// internal secret
Data map[string]string
// external secret
SecretProviderID string
Path string
}
type CreateSecretHandler struct {
log *zap.SugaredLogger
configstoreClient *csapi.Client
}
func (h *ActionHandler) CreateSecret(ctx context.Context, req *CreateSecretRequest) (*csapi.Secret, error) {
if !util.ValidateName(req.Name) {
return nil, util.NewErrBadRequest(errors.Errorf("invalid secret name %q", req.Name))
}
s := &types.Secret{
Name: req.Name,
Type: req.Type,
Data: req.Data,
}
var resp *http.Response
var rs *csapi.Secret
var err error
switch req.ParentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("creating project group secret")
rs, resp, err = h.configstoreClient.CreateProjectGroupSecret(ctx, req.ParentRef, s)
case types.ConfigTypeProject:
h.log.Infof("creating project secret")
rs, resp, err = h.configstoreClient.CreateProjectSecret(ctx, req.ParentRef, s)
}
if err != nil {
return nil, ErrFromRemote(resp, errors.Wrapf(err, "failed to create secret"))
}
h.log.Infof("secret %s created, ID: %s", rs.Name, rs.ID)
return rs, nil
}
func (h *ActionHandler) DeleteSecret(ctx context.Context, parentType types.ConfigType, parentRef, name string) error {
var resp *http.Response
var err error
switch parentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("deleting project group secret")
resp, err = h.configstoreClient.DeleteProjectGroupSecret(ctx, parentRef, name)
case types.ConfigTypeProject:
h.log.Infof("deleting project secret")
resp, err = h.configstoreClient.DeleteProjectSecret(ctx, parentRef, name)
}
if err != nil {
return ErrFromRemote(resp, errors.Wrapf(err, "failed to delete secret"))
}
return nil
}

View File

@ -19,12 +19,12 @@ import (
"net/http"
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
"github.com/sorintlab/agola/internal/services/gateway/action"
"github.com/sorintlab/agola/internal/services/types"
"github.com/sorintlab/agola/internal/util"
"go.uber.org/zap"
"github.com/gorilla/mux"
"github.com/pkg/errors"
)
type SecretResponse struct {
@ -42,12 +42,12 @@ func createSecretResponse(s *csapi.Secret) *SecretResponse {
}
type SecretHandler struct {
log *zap.SugaredLogger
configstoreClient *csapi.Client
log *zap.SugaredLogger
ah *action.ActionHandler
}
func NewSecretHandler(logger *zap.Logger, configstoreClient *csapi.Client) *SecretHandler {
return &SecretHandler{log: logger.Sugar(), configstoreClient: configstoreClient}
func NewSecretHandler(logger *zap.Logger, ah *action.ActionHandler) *SecretHandler {
return &SecretHandler{log: logger.Sugar(), ah: ah}
}
func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -61,15 +61,13 @@ func (h *SecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
var cssecrets []*csapi.Secret
var resp *http.Response
switch parentType {
case types.ConfigTypeProjectGroup:
cssecrets, resp, err = h.configstoreClient.GetProjectGroupSecrets(ctx, parentRef, tree)
case types.ConfigTypeProject:
cssecrets, resp, err = h.configstoreClient.GetProjectSecrets(ctx, parentRef, tree)
areq := &action.GetSecretsRequest{
ParentType: parentType,
ParentRef: parentRef,
Tree: tree,
}
if httpErrorFromRemote(w, resp, err) {
cssecrets, err := h.ah.GetSecrets(ctx, areq)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}
@ -98,12 +96,12 @@ type CreateSecretRequest struct {
}
type CreateSecretHandler struct {
log *zap.SugaredLogger
configstoreClient *csapi.Client
log *zap.SugaredLogger
ah *action.ActionHandler
}
func NewCreateSecretHandler(logger *zap.Logger, configstoreClient *csapi.Client) *CreateSecretHandler {
return &CreateSecretHandler{log: logger.Sugar(), configstoreClient: configstoreClient}
func NewCreateSecretHandler(logger *zap.Logger, ah *action.ActionHandler) *CreateSecretHandler {
return &CreateSecretHandler{log: logger.Sugar(), ah: ah}
}
func (h *CreateSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -120,46 +118,34 @@ func (h *CreateSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
return
}
if !util.ValidateName(req.Name) {
httpError(w, util.NewErrBadRequest(errors.Errorf("invalid secret name %q", req.Name)))
return
areq := &action.CreateSecretRequest{
Name: req.Name,
ParentType: parentType,
ParentRef: parentRef,
Type: req.Type,
Data: req.Data,
SecretProviderID: req.SecretProviderID,
Path: req.Path,
}
s := &types.Secret{
Name: req.Name,
Type: req.Type,
Data: req.Data,
}
var resp *http.Response
var rs *csapi.Secret
switch parentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("creating project group secret")
rs, resp, err = h.configstoreClient.CreateProjectGroupSecret(ctx, parentRef, s)
case types.ConfigTypeProject:
h.log.Infof("creating project secret")
rs, resp, err = h.configstoreClient.CreateProjectSecret(ctx, parentRef, s)
}
if httpErrorFromRemote(w, resp, err) {
cssecret, err := h.ah.CreateSecret(ctx, areq)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}
h.log.Infof("secret %s created, ID: %s", rs.Name, rs.ID)
res := createSecretResponse(rs)
res := createSecretResponse(cssecret)
if err := httpResponse(w, http.StatusOK, res); err != nil {
h.log.Errorf("err: %+v", err)
}
}
type DeleteSecretHandler struct {
log *zap.SugaredLogger
configstoreClient *csapi.Client
log *zap.SugaredLogger
ah *action.ActionHandler
}
func NewDeleteSecretHandler(logger *zap.Logger, configstoreClient *csapi.Client) *DeleteSecretHandler {
return &DeleteSecretHandler{log: logger.Sugar(), configstoreClient: configstoreClient}
func NewDeleteSecretHandler(logger *zap.Logger, ah *action.ActionHandler) *DeleteSecretHandler {
return &DeleteSecretHandler{log: logger.Sugar(), ah: ah}
}
func (h *DeleteSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -172,16 +158,8 @@ func (h *DeleteSecretHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
return
}
var resp *http.Response
switch parentType {
case types.ConfigTypeProjectGroup:
h.log.Infof("deleting project group secret")
resp, err = h.configstoreClient.DeleteProjectGroupSecret(ctx, parentRef, secretName)
case types.ConfigTypeProject:
h.log.Infof("deleting project secret")
resp, err = h.configstoreClient.DeleteProjectSecret(ctx, parentRef, secretName)
}
if httpErrorFromRemote(w, resp, err) {
err = h.ah.DeleteSecret(ctx, parentType, parentRef, secretName)
if httpError(w, err) {
h.log.Errorf("err: %+v", err)
return
}

View File

@ -158,9 +158,9 @@ func (g *Gateway) Run(ctx context.Context) error {
deleteProjectHandler := api.NewDeleteProjectHandler(logger, g.configstoreClient)
projectReconfigHandler := api.NewProjectReconfigHandler(logger, g.ah, g.configstoreClient, g.c.APIExposedURL)
secretHandler := api.NewSecretHandler(logger, g.configstoreClient)
createSecretHandler := api.NewCreateSecretHandler(logger, g.configstoreClient)
deleteSecretHandler := api.NewDeleteSecretHandler(logger, g.configstoreClient)
secretHandler := api.NewSecretHandler(logger, g.ah)
createSecretHandler := api.NewCreateSecretHandler(logger, g.ah)
deleteSecretHandler := api.NewDeleteSecretHandler(logger, g.ah)
variableHandler := api.NewVariableHandler(logger, g.ah)
createVariableHandler := api.NewCreateVariableHandler(logger, g.ah)