From 84a10c0615d12d94472fa0c5fc3028052bc87646 Mon Sep 17 00:00:00 2001 From: Maia Iyer Date: Tue, 6 Aug 2024 22:27:37 -0400 Subject: [PATCH 1/5] Add bundle functions Signed-off-by: Maia Iyer --- api/agent/api.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/api/agent/api.go b/api/agent/api.go index 251e5bf9..57505c00 100644 --- a/api/agent/api.go +++ b/api/agent/api.go @@ -8,6 +8,7 @@ import ( "google.golang.org/grpc/credentials/insecure" agent "github.com/spiffe/spire-api-sdk/proto/spire/api/server/agent/v1" + bundle "github.com/spiffe/spire-api-sdk/proto/spire/api/server/bundle/v1" debugServer "github.com/spiffe/spire-api-sdk/proto/spire/api/server/debug/v1" entry "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1" types "github.com/spiffe/spire-api-sdk/proto/spire/api/types" @@ -215,6 +216,113 @@ func (s *Server) GetTornjakServerInfo(inp GetTornjakServerInfoRequest) (*GetTorn return (*GetTornjakServerInfoResponse)(&s.SpireServerInfo), nil } +// Bundle APIs +type GetBundleRequest bundle.GetBundleRequest +type GetBundleResponse types.Bundle + +func (s *Server) GetBundle(inp GetBundleRequest) (*GetBundleResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + inpReq := bundle.GetBundleRequest(inp) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + var conn *grpc.ClientConn + conn, err := grpc.Dial(s.SpireServerAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + defer conn.Close() + client := bundle.NewBundleClient(conn) + + bundle, err := client.GetBundle(context.Background(), &inpReq) + if err != nil { + return nil, err + } + + return (*GetBundleResponse)(bundle), nil +} + +type ListFederatedBundlesRequest bundle.ListFederatedBundlesRequest +type ListFederatedBundlesResponse bundle.ListFederatedBundlesResponse + +func (s *Server) ListFederatedBundles(inp ListFederatedBundlesRequest) (*ListFederatedBundlesResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + inpReq := bundle.ListFederatedBundlesRequest(inp) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + var conn *grpc.ClientConn + conn, err := grpc.Dial(s.SpireServerAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + defer conn.Close() + client := bundle.NewBundleClient(conn) + + bundle, err := client.ListFederatedBundles(context.Background(), &inpReq) + if err != nil { + return nil, err + } + + return (*ListFederatedBundlesResponse)(bundle), nil +} + +type CreateFederatedBundleRequest bundle.BatchCreateFederatedBundleRequest +type CreateFederatedBundleResponse bundle.BatchCreateFederatedBundleResponse + +func (s *Server) CreateFederatedBundle(inp CreateFederatedBundleRequest) (*CreateFederatedBundleResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + inpReq := bundle.BatchCreateFederatedBundleRequest(inp) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + var conn *grpc.ClientConn + conn, err := grpc.Dial(s.SpireServerAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + defer conn.Close() + client := bundle.NewBundleClient(conn) + + bundle, err := client.BatchCreateFederatedBundle(context.Background(), &inpReq) + if err != nil { + return nil, err + } + + return (*CreateFederatedBundleResponse)(bundle), nil +} + +type UpdateFederatedBundleRequest bundle.BatchUpdateFederatedBundleRequest +type UpdateFederatedBundleResponse bundle.BatchUpdateFederatedBundleResponse + +func (s *Server) UpdateFederatedBundle(inp UpdateFederatedBundleRequest) (*UpdateFederatedBundleResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + inpReq := bundle.BatchUpdateFederatedBundleRequest(inp) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + var conn *grpc.ClientConn + conn, err := grpc.Dial(s.SpireServerAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + defer conn.Close() + client := bundle.NewBundleClient(conn) + + bundle, err := client.BatchUpdateFederatedBundle(context.Background(), &inpReq) + if err != nil { + return nil, err + } + + return (*UpdateFederatedBundleResponse)(bundle), nil +} + +type DeleteFederatedBundleRequest bundle.BatchDeleteFederatedBundleRequest +type DeleteFederatedBundleResponse bundle.BatchDeleteFederatedBundleResponse + +func (s *Server) DeleteFederatedBundle(inp DeleteFederatedBundleRequest) (*DeleteFederatedBundleResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + inpReq := bundle.BatchDeleteFederatedBundleRequest(inp) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet + var conn *grpc.ClientConn + conn, err := grpc.Dial(s.SpireServerAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + defer conn.Close() + client := bundle.NewBundleClient(conn) + + bundle, err := client.BatchDeleteFederatedBundle(context.Background(), &inpReq) + if err != nil { + return nil, err + } + + return (*DeleteFederatedBundleResponse)(bundle), nil +} + + /* Agent From ecd23a8aff16ca24d5c5c9299118418d987efe15 Mon Sep 17 00:00:00 2001 From: Maia Iyer Date: Tue, 6 Aug 2024 22:49:36 -0400 Subject: [PATCH 2/5] add v1 apis Signed-off-by: Maia Iyer --- api/agent/server.go | 207 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/api/agent/server.go b/api/agent/server.go index ef0d743e..6c59213b 100644 --- a/api/agent/server.go +++ b/api/agent/server.go @@ -406,6 +406,208 @@ func (s *Server) entryDelete(w http.ResponseWriter, r *http.Request) { } } +// 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 + } +} + + func cors(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") w.Header().Set("Access-Control-Allow-Origin", "*") @@ -608,6 +810,11 @@ func (s *Server) GetRouter() http.Handler { apiRtr.HandleFunc("/api/v1/spire/entries", s.entryList).Methods("GET") apiRtr.HandleFunc("/api/v1/spire/entries", s.entryCreate).Methods("POST") apiRtr.HandleFunc("/api/v1/spire/entries", s.entryDelete).Methods("DELETE") + apiRtr.HandleFunc("/api/v1/spire/bundles", s.bundleGet).Methods("GET") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleList).Methods("GET") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleCreate).Methods("POST") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleUpdate).Methods("PATCH") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleDelete).Methods("DELETE") // Tornjak specific apiRtr.HandleFunc("/api/v1/tornjak/serverinfo", s.tornjakGetServerInfo).Methods("GET") From 5cf2909bb515b5693285a9b8eeee72e008d23002 Mon Sep 17 00:00:00 2001 From: Maia Iyer Date: Tue, 6 Aug 2024 22:54:46 -0400 Subject: [PATCH 3/5] format nit Signed-off-by: Maia Iyer --- api/agent/server.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/agent/server.go b/api/agent/server.go index 6c59213b..e8f0cc6f 100644 --- a/api/agent/server.go +++ b/api/agent/server.go @@ -810,11 +810,11 @@ func (s *Server) GetRouter() http.Handler { apiRtr.HandleFunc("/api/v1/spire/entries", s.entryList).Methods("GET") apiRtr.HandleFunc("/api/v1/spire/entries", s.entryCreate).Methods("POST") apiRtr.HandleFunc("/api/v1/spire/entries", s.entryDelete).Methods("DELETE") - apiRtr.HandleFunc("/api/v1/spire/bundles", s.bundleGet).Methods("GET") - apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleList).Methods("GET") - apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleCreate).Methods("POST") - apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleUpdate).Methods("PATCH") - apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleDelete).Methods("DELETE") + apiRtr.HandleFunc("/api/v1/spire/bundles", s.bundleGet).Methods("GET") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleList).Methods("GET") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleCreate).Methods("POST") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleUpdate).Methods("PATCH") + apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleDelete).Methods("DELETE") // Tornjak specific apiRtr.HandleFunc("/api/v1/tornjak/serverinfo", s.tornjakGetServerInfo).Methods("GET") From 64e2231d9a6ad6215aad6779f02dd9f9971d543e Mon Sep 17 00:00:00 2001 From: Maia Iyer Date: Wed, 7 Aug 2024 14:51:37 -0400 Subject: [PATCH 4/5] Nit uri fix Signed-off-by: Maia Iyer --- api/agent/server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/agent/server.go b/api/agent/server.go index e8f0cc6f..703e3f69 100644 --- a/api/agent/server.go +++ b/api/agent/server.go @@ -810,7 +810,7 @@ func (s *Server) GetRouter() http.Handler { apiRtr.HandleFunc("/api/v1/spire/entries", s.entryList).Methods("GET") apiRtr.HandleFunc("/api/v1/spire/entries", s.entryCreate).Methods("POST") apiRtr.HandleFunc("/api/v1/spire/entries", s.entryDelete).Methods("DELETE") - apiRtr.HandleFunc("/api/v1/spire/bundles", s.bundleGet).Methods("GET") + apiRtr.HandleFunc("/api/v1/spire/bundle", s.bundleGet).Methods("GET") apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleList).Methods("GET") apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleCreate).Methods("POST") apiRtr.HandleFunc("/api/v1/spire/federations/bundles", s.federatedBundleUpdate).Methods("PATCH") From b8a0986125faafc8ecccc5bdcaf3aa0b315a1d03 Mon Sep 17 00:00:00 2001 From: Maia Iyer Date: Tue, 13 Aug 2024 09:53:24 -0400 Subject: [PATCH 5/5] gofmtted code Signed-off-by: Maia Iyer --- api/agent/api.go | 3 +-- api/agent/server.go | 11 ++++------- api/agent/types.go | 16 ++++++++-------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/api/agent/api.go b/api/agent/api.go index 57505c00..0a6f9287 100644 --- a/api/agent/api.go +++ b/api/agent/api.go @@ -8,7 +8,7 @@ import ( "google.golang.org/grpc/credentials/insecure" agent "github.com/spiffe/spire-api-sdk/proto/spire/api/server/agent/v1" - bundle "github.com/spiffe/spire-api-sdk/proto/spire/api/server/bundle/v1" + bundle "github.com/spiffe/spire-api-sdk/proto/spire/api/server/bundle/v1" debugServer "github.com/spiffe/spire-api-sdk/proto/spire/api/server/debug/v1" entry "github.com/spiffe/spire-api-sdk/proto/spire/api/server/entry/v1" types "github.com/spiffe/spire-api-sdk/proto/spire/api/types" @@ -322,7 +322,6 @@ func (s *Server) DeleteFederatedBundle(inp DeleteFederatedBundleRequest) (*Delet return (*DeleteFederatedBundleResponse)(bundle), nil } - /* Agent diff --git a/api/agent/server.go b/api/agent/server.go index 703e3f69..30816616 100644 --- a/api/agent/server.go +++ b/api/agent/server.go @@ -1,6 +1,7 @@ package api import ( + "crypto/tls" "encoding/json" "fmt" "io" @@ -11,7 +12,6 @@ import ( "path/filepath" "strings" "time" - "crypto/tls" backoff "github.com/cenkalti/backoff/v4" "github.com/gorilla/mux" @@ -20,9 +20,9 @@ import ( "github.com/hashicorp/hcl/hcl/token" "github.com/pkg/errors" - agentdb "github.com/spiffe/tornjak/pkg/agent/db" "github.com/spiffe/tornjak/pkg/agent/authentication/authenticator" "github.com/spiffe/tornjak/pkg/agent/authorization" + agentdb "github.com/spiffe/tornjak/pkg/agent/db" ) type Server struct { @@ -36,9 +36,9 @@ type Server struct { TornjakConfig *TornjakConfig // Plugins - Db agentdb.AgentDB + Db agentdb.AgentDB Authenticator authenticator.Authenticator - Authorizer authorization.Authorizer + Authorizer authorization.Authorizer } // config type, as defined by SPIRE @@ -607,7 +607,6 @@ func (s *Server) federatedBundleDelete(w http.ResponseWriter, r *http.Request) { } } - func cors(w http.ResponseWriter, _ *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") w.Header().Set("Access-Control-Allow-Origin", "*") @@ -760,7 +759,6 @@ func (s *Server) health(w http.ResponseWriter, r *http.Request) { } } - func (s *Server) GetRouter() http.Handler { rtr := mux.NewRouter() @@ -888,7 +886,6 @@ func (s *Server) HandleRequests() { httpsConfig := serverConfig.HTTPSConfig var tlsConfig *tls.Config - if serverConfig.HTTPSConfig.ListenPort == 0 { // Fail because this is required field in this section err = fmt.Errorf("HTTPS Config error: no port configured. Starting insecure HTTP connection at %d...", serverConfig.HTTPConfig.ListenPort) diff --git a/api/agent/types.go b/api/agent/types.go index b5e39911..2e4b14b5 100644 --- a/api/agent/types.go +++ b/api/agent/types.go @@ -27,8 +27,8 @@ type SpireServerConfig struct { } type SPIREConfig struct { - Server *SpireServerConfig `hcl:"server"` - Plugins ast.Node `hcl:"plugins"` + Server *SpireServerConfig `hcl:"server"` + Plugins ast.Node `hcl:"plugins"` } type TornjakConfig struct { @@ -49,9 +49,9 @@ type HTTPConfig struct { } type HTTPSConfig struct { - ListenPort int `hcl:"port"` - Cert string `hcl:"cert"` - Key string `hcl:"key"` + ListenPort int `hcl:"port"` + Cert string `hcl:"cert"` + Key string `hcl:"key"` ClientCA string `hcl:"client_ca"` } @@ -119,12 +119,12 @@ type AuthRole struct { } type APIRoleMapping struct { - Name string `hcl:",key"` + Name string `hcl:",key"` AllowedRoles []string `hcl:"allowed_roles"` } type pluginAuthorizerRBAC struct { - Name string `hcl:"name"` - RoleList []*AuthRole `hcl:"role,block"` + Name string `hcl:"name"` + RoleList []*AuthRole `hcl:"role,block"` APIRoleMappings []*APIRoleMapping `hcl:"API,block"` }