diff --git a/api/agent/cluster_handlers.go b/api/agent/cluster_handlers.go new file mode 100644 index 00000000..dd4d6229 --- /dev/null +++ b/api/agent/cluster_handlers.go @@ -0,0 +1,154 @@ +package api + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strings" +) + +func (s *Server) clusterList(w http.ResponseWriter, r *http.Request) { + var input ListClustersRequest + buf := new(strings.Builder) + + n, err := io.Copy(buf, r.Body) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + data := buf.String() + + if n == 0 { + input = ListClustersRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + } + + ret, err := s.ListClusters(input) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } +} + +func (s *Server) clusterCreate(w http.ResponseWriter, r *http.Request) { + buf := new(strings.Builder) + n, err := io.Copy(buf, r.Body) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + data := buf.String() + var input RegisterClusterRequest + if n == 0 { + input = RegisterClusterRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + } + err = s.DefineCluster(input) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + cors(w, r) + _, err = w.Write([]byte("SUCCESS")) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } +} + +func (s *Server) clusterEdit(w http.ResponseWriter, r *http.Request) { + buf := new(strings.Builder) + n, err := io.Copy(buf, r.Body) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + data := buf.String() + var input EditClusterRequest + if n == 0 { + input = EditClusterRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + } + err = s.EditCluster(input) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + cors(w, r) + _, err = w.Write([]byte("SUCCESS")) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } +} + +func (s *Server) clusterDelete(w http.ResponseWriter, r *http.Request) { + buf := new(strings.Builder) + n, err := io.Copy(buf, r.Body) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + data := buf.String() + var input DeleteClusterRequest + if n == 0 { + input = DeleteClusterRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if err != nil { + emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + } + err = s.DeleteCluster(input) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + cors(w, r) + _, err = w.Write([]byte("SUCCESS")) + if err != nil { + emsg := fmt.Sprintf("Error: %v", err.Error()) + retError(w, emsg, http.StatusBadRequest) + return + } + +} \ No newline at end of file diff --git a/api/agent/crd_handlers.go b/api/agent/crd_handlers.go index 09e027e6..096dc1c7 100644 --- a/api/agent/crd_handlers.go +++ b/api/agent/crd_handlers.go @@ -1,110 +1,86 @@ -package api - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "strings" - "google.golang.org/protobuf/encoding/protojson" - - crdmanager "github.com/spiffe/tornjak/pkg/agent/spirecrd" - trustdomain "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1" -) - -func (s *Server) CRDFederationList(w http.ResponseWriter, r *http.Request) { - // if CRD management not configured - if s.CRDManager == nil { - emsg := "Error: CRD Manager not configured on Tornjak." - retError(w, emsg, http.StatusBadRequest) - return - } - // if CRD management is configured - var input crdmanager.ListFederationRelationshipsRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = crdmanager.ListFederationRelationshipsRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.CRDManager.ListClusterFederatedTrustDomains(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) CRDFederationCreate(w http.ResponseWriter, r *http.Request) { - if s.CRDManager == nil { - emsg := "Error: CRD Manager not configured on Tornjak." - retError(w, emsg, http.StatusBadRequest) - return - } - var input crdmanager.BatchCreateFederationRelationshipsRequest - var rawInput trustdomain.BatchCreateFederationRelationshipRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = crdmanager.BatchCreateFederationRelationshipsRequest{} - } else { - // required to use protojson because of oneof field - err := protojson.Unmarshal([]byte(data), &rawInput) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - input = crdmanager.BatchCreateFederationRelationshipsRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - } - - ret, err := s.CRDManager.BatchCreateClusterFederatedTrustDomains(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} +package api + +import ( + "encoding/json" + "net/http" + "strings" + "google.golang.org/protobuf/encoding/protojson" + + crdmanager "github.com/spiffe/tornjak/pkg/agent/spirecrd" + trustdomain "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1" +) + +func (s *Server) CRDFederationList(w http.ResponseWriter, r *http.Request) { + // if CRD management not configured + if s.CRDManager == nil { + emsg := "Error: CRD Manager not configured on Tornjak." + retError(w, emsg, http.StatusBadRequest) + return + } + // if CRD management is configured + var input crdmanager.ListFederationRelationshipsRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = crdmanager.ListFederationRelationshipsRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) { + return + } + } + + ret, err := s.CRDManager.ListClusterFederatedTrustDomains(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + if isHttpError(err, w, "Error: ", http.StatusInternalServerError) { + return + } + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + + if isHttpError(err, w, "Error: ", http.StatusBadRequest) { + return + } +} + +func (s *Server) CRDFederationCreate(w http.ResponseWriter, r *http.Request) { + if s.CRDManager == nil { + emsg := "Error: CRD Manager not configured on Tornjak." + retError(w, emsg, http.StatusBadRequest) + return + } + var input crdmanager.BatchCreateFederationRelationshipsRequest + var rawInput trustdomain.BatchCreateFederationRelationshipRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = crdmanager.BatchCreateFederationRelationshipsRequest{} + } else { + // required to use protojson because of oneof field + err := protojson.Unmarshal([]byte(data), &rawInput) + if isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) { + return + } + input = crdmanager.BatchCreateFederationRelationshipsRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + } + + ret, err := s.CRDManager.BatchCreateClusterFederatedTrustDomains(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + if isHttpError(err, w, "Error: ", http.StatusInternalServerError) { + return + } + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + + if isHttpError(err, w, "Error: ", http.StatusBadRequest) { + return + } +} \ No newline at end of file diff --git a/api/agent/federation_handlers.go b/api/agent/federation_handlers.go new file mode 100644 index 00000000..a8967cdf --- /dev/null +++ b/api/agent/federation_handlers.go @@ -0,0 +1,135 @@ +package api + +import ( + "encoding/json" + "net/http" + "strings" + + trustdomain "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1" + "google.golang.org/protobuf/encoding/protojson" +) + +// Federation APIs +func (s *Server) federationList(w http.ResponseWriter, r *http.Request) { + var input ListFederationRelationshipsRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = ListFederationRelationshipsRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if (isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest)) { + return + } + } + + ret, err := s.ListFederationRelationships(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + if isHttpError(err, w, "Error: ", http.StatusInternalServerError) { + return + } + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + + if isHttpError(err, w, "Error: ", http.StatusBadRequest) { + return + } +} + +func (s *Server) federationCreate(w http.ResponseWriter, r *http.Request) { + var input CreateFederationRelationshipRequest + var rawInput trustdomain.BatchCreateFederationRelationshipRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = CreateFederationRelationshipRequest{} + } else { + // required to use protojson because of oneof field + err := protojson.Unmarshal([]byte(data), &rawInput) + if isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) { + return; + } + + input = CreateFederationRelationshipRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + } + + ret, err := s.CreateFederationRelationship(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + if isHttpError(err, w, "Error: ", http.StatusInternalServerError) { + return + } + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + if isHttpError(err, w, "Error: ", http.StatusBadRequest) { + return + } +} + +func (s *Server) federationUpdate(w http.ResponseWriter, r *http.Request) { + var input UpdateFederationRelationshipRequest + var rawInput trustdomain.BatchUpdateFederationRelationshipRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = UpdateFederationRelationshipRequest{} + } else { + err := protojson.Unmarshal([]byte(data), &rawInput) + if isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) { + return + } + input = UpdateFederationRelationshipRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + + } + + ret, err := s.UpdateFederationRelationship(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + if isHttpError(err, w, "Error: ", http.StatusInternalServerError) { + return + } + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + if isHttpError(err, w, "Error: ", http.StatusBadRequest) { + return + } +} + +func (s *Server) federationDelete(w http.ResponseWriter, r *http.Request) { + var input DeleteFederationRelationshipRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = DeleteFederationRelationshipRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + if isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) { + return + } + } + + ret, err := s.DeleteFederationRelationship(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + if isHttpError(err, w, "Error: ", http.StatusInternalServerError) { + return + } + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + if isHttpError(err, w, "Error: ", http.StatusBadRequest) { + return + } +} \ No newline at end of file diff --git a/api/agent/handlers.go b/api/agent/handlers.go index d086abd7..bc410217 100644 --- a/api/agent/handlers.go +++ b/api/agent/handlers.go @@ -1,1018 +1,553 @@ -package api - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "strings" - - trustdomain "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1" - "google.golang.org/protobuf/encoding/protojson" -) - -func (s *Server) healthcheck(w http.ResponseWriter, r *http.Request) { - var input HealthcheckRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = HealthcheckRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.SPIREHealthcheck(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) debugServer(w http.ResponseWriter, r *http.Request) { - input := DebugServerRequest{} // HARDCODED INPUT because there are no fields to DebugServerRequest - - ret, err := s.DebugServer(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) agentList(w http.ResponseWriter, r *http.Request) { - var input ListAgentsRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = ListAgentsRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.ListAgents(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) agentBan(w http.ResponseWriter, r *http.Request) { - var input BanAgentRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - emsg := "Error: no data provided" - retError(w, emsg, http.StatusBadRequest) - return - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - err = s.BanAgent(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error listing agents: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - _, err = w.Write([]byte("SUCCESS")) - - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) agentDelete(w http.ResponseWriter, r *http.Request) { - // TODO update backend to also delete agent metadata - - var input DeleteAgentRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - emsg := "Error: no data provided" - retError(w, emsg, http.StatusBadRequest) - return - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - err = s.DeleteAgent(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error listing agents: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - _, err = w.Write([]byte("SUCCESS")) - - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) agentCreateJoinToken(w http.ResponseWriter, r *http.Request) { - var input CreateJoinTokenRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = CreateJoinTokenRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.CreateJoinToken(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) entryList(w http.ResponseWriter, r *http.Request) { - var input ListEntriesRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = ListEntriesRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.ListEntries(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) entryCreate(w http.ResponseWriter, r *http.Request) { - var input BatchCreateEntryRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = BatchCreateEntryRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.BatchCreateEntry(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -func (s *Server) entryDelete(w http.ResponseWriter, r *http.Request) { - var input BatchDeleteEntryRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = BatchDeleteEntryRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.BatchDeleteEntry(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -// Bundle APIs -func (s *Server) bundleGet(w http.ResponseWriter, r *http.Request) { - var input GetBundleRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = GetBundleRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.GetBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federatedBundleList(w http.ResponseWriter, r *http.Request) { - var input ListFederatedBundlesRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = ListFederatedBundlesRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.ListFederatedBundles(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federatedBundleCreate(w http.ResponseWriter, r *http.Request) { - var input CreateFederatedBundleRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = CreateFederatedBundleRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.CreateFederatedBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federatedBundleUpdate(w http.ResponseWriter, r *http.Request) { - var input UpdateFederatedBundleRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = UpdateFederatedBundleRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.UpdateFederatedBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federatedBundleDelete(w http.ResponseWriter, r *http.Request) { - var input DeleteFederatedBundleRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = DeleteFederatedBundleRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.DeleteFederatedBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -// Federation APIs -func (s *Server) federationList(w http.ResponseWriter, r *http.Request) { - var input ListFederationRelationshipsRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = ListFederationRelationshipsRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.ListFederationRelationships(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federationCreate(w http.ResponseWriter, r *http.Request) { - var input CreateFederationRelationshipRequest - var rawInput trustdomain.BatchCreateFederationRelationshipRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = CreateFederationRelationshipRequest{} - } else { - // required to use protojson because of oneof field - err := protojson.Unmarshal([]byte(data), &rawInput) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - input = CreateFederationRelationshipRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - } - - ret, err := s.CreateFederationRelationship(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federationUpdate(w http.ResponseWriter, r *http.Request) { - var input UpdateFederationRelationshipRequest - var rawInput trustdomain.BatchUpdateFederationRelationshipRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = UpdateFederationRelationshipRequest{} - } else { - err := protojson.Unmarshal([]byte(data), &rawInput) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - input = UpdateFederationRelationshipRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - - } - - ret, err := s.UpdateFederationRelationship(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) federationDelete(w http.ResponseWriter, r *http.Request) { - var input DeleteFederationRelationshipRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = DeleteFederationRelationshipRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.DeleteFederationRelationship(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusInternalServerError) - return - } - - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -// Tornjak Handlers -func (s *Server) home(w http.ResponseWriter, r *http.Request) { - var ret = "Welcome to the Tornjak Backend!" - - cors(w, r) - je := json.NewEncoder(w) - - var err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - } -} - -func (s *Server) health(w http.ResponseWriter, r *http.Request) { - var ret = "Endpoint is healthy." - - cors(w, r) - je := json.NewEncoder(w) - - var err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - } -} - -func (s *Server) tornjakSelectorsList(w http.ResponseWriter, r *http.Request) { - buf := new(strings.Builder) - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - var input ListSelectorsRequest - if n == 0 { - input = ListSelectorsRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - ret, err := s.ListSelectors(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) tornjakPluginDefine(w http.ResponseWriter, r *http.Request) { - buf := new(strings.Builder) - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - var input RegisterSelectorRequest - if n == 0 { - input = RegisterSelectorRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - err = s.DefineSelectors(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - _, err = w.Write([]byte("SUCCESS")) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) tornjakAgentsList(w http.ResponseWriter, r *http.Request) { - buf := new(strings.Builder) - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - var input ListAgentMetadataRequest - if n == 0 { - input = ListAgentMetadataRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - ret, err := s.ListAgentMetadata(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -/********* CLUSTER *********/ - -func (s *Server) clusterList(w http.ResponseWriter, r *http.Request) { - var input ListClustersRequest - buf := new(strings.Builder) - - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - - if n == 0 { - input = ListClustersRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - - ret, err := s.ListClusters(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - je := json.NewEncoder(w) - err = je.Encode(ret) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) clusterCreate(w http.ResponseWriter, r *http.Request) { - buf := new(strings.Builder) - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - var input RegisterClusterRequest - if n == 0 { - input = RegisterClusterRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - err = s.DefineCluster(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - _, err = w.Write([]byte("SUCCESS")) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) clusterEdit(w http.ResponseWriter, r *http.Request) { - buf := new(strings.Builder) - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - var input EditClusterRequest - if n == 0 { - input = EditClusterRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - err = s.EditCluster(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - _, err = w.Write([]byte("SUCCESS")) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } -} - -func (s *Server) clusterDelete(w http.ResponseWriter, r *http.Request) { - buf := new(strings.Builder) - n, err := io.Copy(buf, r.Body) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - data := buf.String() - var input DeleteClusterRequest - if n == 0 { - input = DeleteClusterRequest{} - } else { - err := json.Unmarshal([]byte(data), &input) - if err != nil { - emsg := fmt.Sprintf("Error parsing data: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - } - err = s.DeleteCluster(input) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - cors(w, r) - _, err = w.Write([]byte("SUCCESS")) - if err != nil { - emsg := fmt.Sprintf("Error: %v", err.Error()) - retError(w, emsg, http.StatusBadRequest) - return - } - -} - -/********* END CLUSTER *********/ +package api + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strings" +) + +// Checks for httpError; meant to replace the (about) 4 chunks of error checking code run per function +/* @param status can be: + 1 -> http.StatusBadRequest + 2 -> http.StatusInternalServerError + + @param emsg can be one of three: + 1 -> "Error parsing data: %v", err.Error() + 2 -> "Error: %v", err.Error() + 3 -> "Error listing agents: %v", err.Error() + NOTE: Error message 1 ONLY returns with http.StatusBadRequest. Messages 2 and 3 can return with either +*/ +func isHttpError(err error, w http.ResponseWriter, emsg string, status int) (bool){ + if err != nil { + retError(w, emsg + fmt.Sprintf("%v",err.Error()), status); + return true + } + return false +} + +// meant to replace the 4 lines of code repeated throughout most functions + // that copies the body of http.Request into buf and returns results in n and err +/* @param emsg can be one of three: + 1 -> "Error parsing data: %v", err.Error() + 2 -> "Error: %v", err.Error() + 3 -> "Error listing agents: %v", err.Error() +*/ +func copyIntoBuff(buf *strings.Builder, w http.ResponseWriter, r *http.Request, emsg string) (int64, error, string){ + fmt.Print("made it 2") + n, err := io.Copy(buf, r.Body) + isErr := isHttpError(err, w, emsg + fmt.Sprintf("%v", err.Error()), http.StatusBadRequest) + if isErr {return 0, err, "err"} + data := buf.String() + + return n, err, data +} + +// Gets called from GetRouter func in server.go +// http is a type of command that the server can take that starts the server +// Gives an explicit return only if an error is countered + // otherwise, since no return is outlined, no return is necessary +func (s *Server) healthcheck(w http.ResponseWriter, r *http.Request) { + + // To store the HealthcheckRequest we get from grpc + var input HealthcheckRequest + buf := new(strings.Builder) + + // copies body of http.Request into buf + // and then puts the # of bytes of type int64 into n and an error into err + // err is nil if there was no error + // n is 0 and data is "err" if err was not nil inside of copyIntoBuff + fmt.Print("made it 1") + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + fmt.Print("made it 3") + if n == 0 && data == "err" { return } + + // if the body of the request was empty + if n == 0 { + input = HealthcheckRequest{} + + // else if the body was NOT empty + // unmarshal the JSON and check for errors + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + // ret gets the address to the HealthcheckReponse response + // the HealthcheckResponse is actually the response of the server "input" as returned by grpc's HealthClient.Check() + ret, err := s.SPIREHealthcheck(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + // Sets the headers associated with the request to specific values + /* + "Content-Type" --> "application/json;charset=UTF-8" + "Access-Control-Allow-Origin" --> "*" + "Access-Control-Allow-Methods" --> "POST, GET, OPTIONS, DELETE, PATCH" + "Access-Control-Allow-Headers" --> "Content-Type, access-control-allow-origin, access-control-allow-headers, access-control-allow-credentials, Authorization, access-control-allow-methods" + "Access-Control-Expose-Headers" --> "*, Authorization" + */ + cors(w, r) + + // Creates an Encoder object pointer that will be writing to http.ResponseWriter w + je := json.NewEncoder(w) + + // writing the JSON encoing of ret + // (address to the HealtheckResponse of whatever server we're checking) + // to http.ResponseWriter w + err = je.Encode(ret) + + // if the Encode failed + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + + // if we never return an error, then all is well! +} + +func (s *Server) debugServer(w http.ResponseWriter, r *http.Request) { + input := DebugServerRequest{} // HARDCODED INPUT because there are no fields to DebugServerRequest + + ret, err := s.DebugServer(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) agentList(w http.ResponseWriter, r *http.Request) { + var input ListAgentsRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = ListAgentsRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.ListAgents(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + +} + +func (s *Server) agentBan(w http.ResponseWriter, r *http.Request) { + var input BanAgentRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + emsg := "Error: no data provided" + retError(w, emsg, http.StatusBadRequest) + return + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + err = s.BanAgent(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error listing agents: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + _, err = w.Write([]byte("SUCCESS")) + + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + +} + +func (s *Server) agentDelete(w http.ResponseWriter, r *http.Request) { + // TODO update backend to also delete agent metadata + + var input DeleteAgentRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + emsg := "Error: no data provided" + retError(w, emsg, http.StatusBadRequest) + return + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + err = s.DeleteAgent(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error listing agents: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + _, err = w.Write([]byte("SUCCESS")) + + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + +} + +func (s *Server) agentCreateJoinToken(w http.ResponseWriter, r *http.Request) { + var input CreateJoinTokenRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = CreateJoinTokenRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.CreateJoinToken(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + +} + +func (s *Server) entryList(w http.ResponseWriter, r *http.Request) { + var input ListEntriesRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = ListEntriesRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.ListEntries(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + +} + +func (s *Server) entryCreate(w http.ResponseWriter, r *http.Request) { + var input BatchCreateEntryRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = BatchCreateEntryRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.BatchCreateEntry(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + +} + +func (s *Server) entryDelete(w http.ResponseWriter, r *http.Request) { + var input BatchDeleteEntryRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = BatchDeleteEntryRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.BatchDeleteEntry(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +// Bundle APIs +func (s *Server) bundleGet(w http.ResponseWriter, r *http.Request) { + var input GetBundleRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = GetBundleRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.GetBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) federatedBundleList(w http.ResponseWriter, r *http.Request) { + var input ListFederatedBundlesRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = ListFederatedBundlesRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.ListFederatedBundles(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) federatedBundleCreate(w http.ResponseWriter, r *http.Request) { + var input CreateFederatedBundleRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = CreateFederatedBundleRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.CreateFederatedBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) federatedBundleUpdate(w http.ResponseWriter, r *http.Request) { + var input UpdateFederatedBundleRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + if n == 0 { + input = UpdateFederatedBundleRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.UpdateFederatedBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) federatedBundleDelete(w http.ResponseWriter, r *http.Request) { + var input DeleteFederatedBundleRequest + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + if n == 0 { + input = DeleteFederatedBundleRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.DeleteFederatedBundle(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + isErr := isHttpError(err, w, "Error: ", http.StatusInternalServerError) + if isErr {return} + + cors(w, r) + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +// Tornjak Handlers +func (s *Server) home(w http.ResponseWriter, r *http.Request) { + var ret = "Welcome to the Tornjak Backend!" + + cors(w, r) + je := json.NewEncoder(w) + + var err = je.Encode(ret) + isErr := isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) health(w http.ResponseWriter, r *http.Request) { + var ret = "Endpoint is healthy." + + cors(w, r) + je := json.NewEncoder(w) + + var err = je.Encode(ret) + isErr := isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) tornjakSelectorsList(w http.ResponseWriter, r *http.Request) { + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + var input ListSelectorsRequest + + if n == 0 { + input = ListSelectorsRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.ListSelectors(input) + isErr := isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + + cors(w, r) + + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) tornjakPluginDefine(w http.ResponseWriter, r *http.Request) { + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + var input RegisterSelectorRequest + + if n == 0 { + input = RegisterSelectorRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + err = s.DefineSelectors(input) + isErr := isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + + cors(w, r) + + _, err = w.Write([]byte("SUCCESS")) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +} + +func (s *Server) tornjakAgentsList(w http.ResponseWriter, r *http.Request) { + buf := new(strings.Builder) + + n, err, data := copyIntoBuff(buf, w, r, "Error parsing data: ") + if n == 0 && data == "err" { return } + + var input ListAgentMetadataRequest + + if n == 0 { + input = ListAgentMetadataRequest{} + } else { + err := json.Unmarshal([]byte(data), &input) + isErr := isHttpError(err, w, "Error parsing data: ", http.StatusBadRequest) + if isErr {return} + } + + ret, err := s.ListAgentMetadata(input) + isErr := isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} + + cors(w, r) + + je := json.NewEncoder(w) + err = je.Encode(ret) + isErr = isHttpError(err, w, "Error: ", http.StatusBadRequest) + if isErr {return} +}