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 }