Skip to content

Commit

Permalink
Add POST ClusterFederatedTrustDomain API (spiffe#549)
Browse files Browse the repository at this point in the history
* removed handlers

Signed-off-by: Maia Iyer <[email protected]>

* nit spacing fixes

Signed-off-by: Maia Iyer <[email protected]>

* Nits

Signed-off-by: Maia Iyer <[email protected]>

* Nits

Signed-off-by: Maia Iyer <[email protected]>

* Initialize Package

Signed-off-by: Maia Iyer <[email protected]>

* added documentation

Signed-off-by: Maia Iyer <[email protected]>

* nit

Signed-off-by: Maia Iyer <[email protected]>

* nit lints

Signed-off-by: Maia Iyer <[email protected]>

* fix key length check

Signed-off-by: Maia Iyer <[email protected]>

* add list federation function to crd pkg

Signed-off-by: Maia Iyer <[email protected]>

* try printing individual crds

Signed-off-by: Maia Iyer <[email protected]>

* Added parsing code and refactored

Signed-off-by: Maia Iyer <[email protected]>

* return result value

Signed-off-by: Maia Iyer <[email protected]>

* Removing print statements

Signed-off-by: Maia Iyer <[email protected]>

* Added Documentation

Signed-off-by: Maia Iyer <[email protected]>

* nits

Signed-off-by: Maia Iyer <[email protected]>

* add route

Signed-off-by: Maia Iyer <[email protected]>

* add type conversions

Signed-off-by: Maia Iyer <[email protected]>

* Finished Type Conversion

Signed-off-by: Maia Iyer <[email protected]>

* add nil check

Signed-off-by: Maia Iyer <[email protected]>

* create object

Signed-off-by: Maia Iyer <[email protected]>

* Added return values

Signed-off-by: Maia Iyer <[email protected]>

* nit code refactor

Signed-off-by: Maia Iyer <[email protected]>

---------

Signed-off-by: Maia Iyer <[email protected]>
  • Loading branch information
maia-iyer authored Jan 21, 2025
1 parent 53707ca commit 34cf316
Show file tree
Hide file tree
Showing 5 changed files with 400 additions and 18 deletions.
51 changes: 51 additions & 0 deletions api/agent/crd_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"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) {
Expand Down Expand Up @@ -57,3 +59,52 @@ func (s *Server) CRDFederationList(w http.ResponseWriter, r *http.Request) {
}

}

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
}
}
1 change: 1 addition & 0 deletions api/agent/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ func (s *Server) GetRouter() http.Handler {

// SPIRE CRD Federations
apiRtr.HandleFunc("/api/v1/spire-controller-manager/clusterfederatedtrustdomains", s.CRDFederationList).Methods(http.MethodGet, http.MethodOptions)
apiRtr.HandleFunc("/api/v1/spire-controller-manager/clusterfederatedtrustdomains", s.CRDFederationCreate).Methods(http.MethodPost)

// Tornjak specific
apiRtr.HandleFunc("/api/v1/tornjak/serverinfo", s.tornjakGetServerInfo).Methods(http.MethodGet, http.MethodOptions)
Expand Down
74 changes: 56 additions & 18 deletions pkg/agent/spirecrd/federation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import (
"context"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"

spirev1alpha1 "github.com/spiffe/spire-controller-manager/api/v1alpha1"
)

var gvrFederation = schema.GroupVersionResource{
Expand All @@ -31,29 +28,70 @@ func (s *SPIRECRDManager) ListClusterFederatedTrustDomains(inp ListFederationRel

var result []*apitypes.FederationRelationship
for _, trustDomain := range trustDomainList.Items {
// parse TrustDomain into ClusterFederatedTrustDomain object
var clusterFederatedTrustDomain spirev1alpha1.ClusterFederatedTrustDomain
err := runtime.DefaultUnstructuredConverter.FromUnstructured(trustDomain.Object, &clusterFederatedTrustDomain)
spireAPIFederation, err := unstructuredToSpireAPIFederation(trustDomain)
if err != nil {
return ListFederationRelationshipsResponse{}, fmt.Errorf("error parsing trustdomain: %v", err)
return ListFederationRelationshipsResponse{}, fmt.Errorf("Error parsing trustDomain: %v", err)
}
// place SPIRE API object into result
result = append(result, spireAPIFederation)
}

return ListFederationRelationshipsResponse{
FederationRelationships: result,
}, nil
}

type BatchCreateFederationRelationshipsRequest trustdomain.BatchCreateFederationRelationshipRequest
type BatchCreateFederationRelationshipsResponse trustdomain.BatchCreateFederationRelationshipResponse

func (s *SPIRECRDManager) BatchCreateClusterFederatedTrustDomains(inp BatchCreateFederationRelationshipsRequest) (BatchCreateFederationRelationshipsResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet

// TODO add check on classname - should only make for a certain classname
apiFederationList := inp.FederationRelationships
var result []*trustdomain.BatchCreateFederationRelationshipResponse_Result
for _, apiFederation := range apiFederationList {
// resulting object
successStatus := &apitypes.Status{
Code: 0,
Message: "OK",
}
// parse ClusterFederatedTrustDomain object into Federation object
federation, err := spirev1alpha1.ParseClusterFederatedTrustDomainSpec(&clusterFederatedTrustDomain.Spec)
failStatus := &apitypes.Status{
Code: 1, // TODO more specific codes
Message: "Failure",
}

// parse to unstructured
createInput, err := s.spireAPIFederationToUnstructured(apiFederation)
if err != nil {
return ListFederationRelationshipsResponse{}, fmt.Errorf("error parsing crd spec: %v", err)
failStatus.Message = fmt.Sprintf("Error parsing input: %v", err)
result = append(result, &trustdomain.BatchCreateFederationRelationshipResponse_Result {Status: failStatus})
continue
}

// parse Federation object into spire API object
spireAPIFederation, err := federationRelationshipToAPI(*federation)
// post ClusterFederatedTrustDomain object
createResult, err := s.kubeClient.Resource(gvrFederation).Create(context.TODO(), createInput, metav1.CreateOptions{})
if err != nil {
failStatus.Message = fmt.Sprintf("Error listing trust dmoains: %v", err)
result = append(result, &trustdomain.BatchCreateFederationRelationshipResponse_Result {Status: failStatus})
continue
}
resultFederationRelationship, err := unstructuredToSpireAPIFederation(*createResult)
if err != nil {
return ListFederationRelationshipsResponse{}, fmt.Errorf("error parsing into spire API object: %v", err)
failStatus.Message = fmt.Sprintf("Error parsing returned trust domain: %v", err)
result = append(result, &trustdomain.BatchCreateFederationRelationshipResponse_Result {Status: failStatus})
continue
}
resultEntry := trustdomain.BatchCreateFederationRelationshipResponse_Result{
Status: successStatus,
FederationRelationship: resultFederationRelationship,
}

// place SPIRE API object into result
result = append(result, spireAPIFederation)
}
result = append(result, &resultEntry)

return ListFederationRelationshipsResponse{
FederationRelationships: result,
}
return BatchCreateFederationRelationshipsResponse{
Results: result,
}, nil
}


Loading

0 comments on commit 34cf316

Please sign in to comment.