github.com/freiheit-com/kuberpult@v1.24.2-0.20240328135542-315d5630abe6/services/frontend-service/pkg/handler/environments.go (about)

     1  /*This file is part of kuberpult.
     2  
     3  Kuberpult is free software: you can redistribute it and/or modify
     4  it under the terms of the Expat(MIT) License as published by
     5  the Free Software Foundation.
     6  
     7  Kuberpult is distributed in the hope that it will be useful,
     8  but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    10  MIT License for more details.
    11  
    12  You should have received a copy of the MIT License
    13  along with kuberpult. If not, see <https://directory.fsf.org/wiki/License:Expat>.
    14  
    15  Copyright 2023 freiheit.com*/
    16  
    17  package handler
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"net/http"
    24  
    25  	"github.com/ProtonMail/go-crypto/openpgp"
    26  	pgperrors "github.com/ProtonMail/go-crypto/openpgp/errors"
    27  	api "github.com/freiheit-com/kuberpult/pkg/api/v1"
    28  )
    29  
    30  const (
    31  	MAXIMUM_MULTIPART_SIZE = 12 * 1024 * 1024 // = 12Mi
    32  )
    33  
    34  func (s Server) handleCreateEnvironment(w http.ResponseWriter, req *http.Request, environment, tail string) {
    35  
    36  	if tail != "/" {
    37  		http.Error(w, fmt.Sprintf("Create Environment does not accept additional path arguments, got: '%s'", tail), http.StatusNotFound)
    38  		return
    39  	}
    40  	if err := req.ParseMultipartForm(MAXIMUM_MULTIPART_SIZE); err != nil {
    41  		w.WriteHeader(http.StatusBadRequest)
    42  		fmt.Fprintf(w, "Invalid body: %s", err)
    43  		return
    44  	}
    45  
    46  	form := req.MultipartForm
    47  	//exhaustruct:ignore
    48  	envConfig := api.EnvironmentConfig{}
    49  
    50  	config, ok := form.Value["config"]
    51  	if !ok {
    52  		w.WriteHeader(http.StatusBadRequest)
    53  		w.Write([]byte("Missing config in request body")) //nolint:errcheck
    54  		return
    55  	}
    56  	err := json.Unmarshal([]byte(config[0]), &envConfig)
    57  	if err != nil {
    58  		w.WriteHeader(http.StatusBadRequest)
    59  		fmt.Fprintf(w, "Invalid body: %s", err)
    60  		return
    61  	}
    62  
    63  	if signature, ok := form.Value["signature"]; ok {
    64  		if _, err := openpgp.CheckArmoredDetachedSignature(s.KeyRing, bytes.NewReader([]byte(config[0])), bytes.NewReader([]byte(signature[0])), nil); err != nil {
    65  			if err != pgperrors.ErrUnknownIssuer {
    66  				w.WriteHeader(http.StatusInternalServerError)
    67  				fmt.Fprintf(w, "Internal: Invalid Signature: %s", err)
    68  				return
    69  			}
    70  			w.WriteHeader(http.StatusUnauthorized)
    71  			fmt.Fprintf(w, "Invalid signature")
    72  			return
    73  		}
    74  	} else if s.AzureAuth {
    75  		w.WriteHeader(http.StatusBadRequest)
    76  		w.Write([]byte("Missing signature in request body")) //nolint:errcheck
    77  		return
    78  	}
    79  
    80  	_, err = s.BatchClient.ProcessBatch(req.Context(),
    81  		&api.BatchRequest{Actions: []*api.BatchAction{
    82  			{Action: &api.BatchAction_CreateEnvironment{
    83  				CreateEnvironment: &api.CreateEnvironmentRequest{
    84  					Environment: environment,
    85  					Config:      &envConfig,
    86  				}}},
    87  		},
    88  		})
    89  
    90  	if err != nil {
    91  		handleGRPCError(req.Context(), w, err)
    92  		return
    93  	}
    94  	w.WriteHeader(http.StatusOK)
    95  }