Skip to content

Commit 34cf316

Browse files
authored
Add POST ClusterFederatedTrustDomain API (#549)
* 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]>
1 parent 53707ca commit 34cf316

File tree

5 files changed

+400
-18
lines changed

5 files changed

+400
-18
lines changed

api/agent/crd_handlers.go

+51
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"io"
77
"net/http"
88
"strings"
9+
"google.golang.org/protobuf/encoding/protojson"
910

1011
crdmanager "github.com/spiffe/tornjak/pkg/agent/spirecrd"
12+
trustdomain "github.com/spiffe/spire-api-sdk/proto/spire/api/server/trustdomain/v1"
1113
)
1214

1315
func (s *Server) CRDFederationList(w http.ResponseWriter, r *http.Request) {
@@ -57,3 +59,52 @@ func (s *Server) CRDFederationList(w http.ResponseWriter, r *http.Request) {
5759
}
5860

5961
}
62+
63+
func (s *Server) CRDFederationCreate(w http.ResponseWriter, r *http.Request) {
64+
if s.CRDManager == nil {
65+
emsg := "Error: CRD Manager not configured on Tornjak."
66+
retError(w, emsg, http.StatusBadRequest)
67+
return
68+
}
69+
var input crdmanager.BatchCreateFederationRelationshipsRequest
70+
var rawInput trustdomain.BatchCreateFederationRelationshipRequest
71+
buf := new(strings.Builder)
72+
73+
n, err := io.Copy(buf, r.Body)
74+
if err != nil {
75+
emsg := fmt.Sprintf("Error parsing data: %v", err.Error())
76+
retError(w, emsg, http.StatusBadRequest)
77+
return
78+
}
79+
data := buf.String()
80+
81+
if n == 0 {
82+
input = crdmanager.BatchCreateFederationRelationshipsRequest{}
83+
} else {
84+
// required to use protojson because of oneof field
85+
err := protojson.Unmarshal([]byte(data), &rawInput)
86+
if err != nil {
87+
emsg := fmt.Sprintf("Error parsing data: %v", err.Error())
88+
retError(w, emsg, http.StatusBadRequest)
89+
return
90+
}
91+
input = crdmanager.BatchCreateFederationRelationshipsRequest(rawInput) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet
92+
}
93+
94+
ret, err := s.CRDManager.BatchCreateClusterFederatedTrustDomains(input) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet
95+
if err != nil {
96+
emsg := fmt.Sprintf("Error: %v", err.Error())
97+
retError(w, emsg, http.StatusInternalServerError)
98+
return
99+
}
100+
101+
cors(w, r)
102+
je := json.NewEncoder(w)
103+
err = je.Encode(ret) //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet
104+
105+
if err != nil {
106+
emsg := fmt.Sprintf("Error: %v", err.Error())
107+
retError(w, emsg, http.StatusBadRequest)
108+
return
109+
}
110+
}

api/agent/server.go

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ func (s *Server) GetRouter() http.Handler {
214214

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

218219
// Tornjak specific
219220
apiRtr.HandleFunc("/api/v1/tornjak/serverinfo", s.tornjakGetServerInfo).Methods(http.MethodGet, http.MethodOptions)

pkg/agent/spirecrd/federation.go

+56-18
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ import (
77
"context"
88

99
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10-
"k8s.io/apimachinery/pkg/runtime"
1110
"k8s.io/apimachinery/pkg/runtime/schema"
12-
13-
spirev1alpha1 "github.com/spiffe/spire-controller-manager/api/v1alpha1"
1411
)
1512

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

3229
var result []*apitypes.FederationRelationship
3330
for _, trustDomain := range trustDomainList.Items {
34-
// parse TrustDomain into ClusterFederatedTrustDomain object
35-
var clusterFederatedTrustDomain spirev1alpha1.ClusterFederatedTrustDomain
36-
err := runtime.DefaultUnstructuredConverter.FromUnstructured(trustDomain.Object, &clusterFederatedTrustDomain)
31+
spireAPIFederation, err := unstructuredToSpireAPIFederation(trustDomain)
3732
if err != nil {
38-
return ListFederationRelationshipsResponse{}, fmt.Errorf("error parsing trustdomain: %v", err)
33+
return ListFederationRelationshipsResponse{}, fmt.Errorf("Error parsing trustDomain: %v", err)
34+
}
35+
// place SPIRE API object into result
36+
result = append(result, spireAPIFederation)
37+
}
38+
39+
return ListFederationRelationshipsResponse{
40+
FederationRelationships: result,
41+
}, nil
42+
}
43+
44+
type BatchCreateFederationRelationshipsRequest trustdomain.BatchCreateFederationRelationshipRequest
45+
type BatchCreateFederationRelationshipsResponse trustdomain.BatchCreateFederationRelationshipResponse
46+
47+
func (s *SPIRECRDManager) BatchCreateClusterFederatedTrustDomains(inp BatchCreateFederationRelationshipsRequest) (BatchCreateFederationRelationshipsResponse, error) { //nolint:govet //Ignoring mutex (not being used) - sync.Mutex by value is unused for linter govet
48+
49+
// TODO add check on classname - should only make for a certain classname
50+
apiFederationList := inp.FederationRelationships
51+
var result []*trustdomain.BatchCreateFederationRelationshipResponse_Result
52+
for _, apiFederation := range apiFederationList {
53+
// resulting object
54+
successStatus := &apitypes.Status{
55+
Code: 0,
56+
Message: "OK",
3957
}
40-
// parse ClusterFederatedTrustDomain object into Federation object
41-
federation, err := spirev1alpha1.ParseClusterFederatedTrustDomainSpec(&clusterFederatedTrustDomain.Spec)
58+
failStatus := &apitypes.Status{
59+
Code: 1, // TODO more specific codes
60+
Message: "Failure",
61+
}
62+
63+
// parse to unstructured
64+
createInput, err := s.spireAPIFederationToUnstructured(apiFederation)
4265
if err != nil {
43-
return ListFederationRelationshipsResponse{}, fmt.Errorf("error parsing crd spec: %v", err)
66+
failStatus.Message = fmt.Sprintf("Error parsing input: %v", err)
67+
result = append(result, &trustdomain.BatchCreateFederationRelationshipResponse_Result {Status: failStatus})
68+
continue
4469
}
4570

46-
// parse Federation object into spire API object
47-
spireAPIFederation, err := federationRelationshipToAPI(*federation)
71+
// post ClusterFederatedTrustDomain object
72+
createResult, err := s.kubeClient.Resource(gvrFederation).Create(context.TODO(), createInput, metav1.CreateOptions{})
73+
if err != nil {
74+
failStatus.Message = fmt.Sprintf("Error listing trust dmoains: %v", err)
75+
result = append(result, &trustdomain.BatchCreateFederationRelationshipResponse_Result {Status: failStatus})
76+
continue
77+
}
78+
resultFederationRelationship, err := unstructuredToSpireAPIFederation(*createResult)
4879
if err != nil {
49-
return ListFederationRelationshipsResponse{}, fmt.Errorf("error parsing into spire API object: %v", err)
80+
failStatus.Message = fmt.Sprintf("Error parsing returned trust domain: %v", err)
81+
result = append(result, &trustdomain.BatchCreateFederationRelationshipResponse_Result {Status: failStatus})
82+
continue
83+
}
84+
resultEntry := trustdomain.BatchCreateFederationRelationshipResponse_Result{
85+
Status: successStatus,
86+
FederationRelationship: resultFederationRelationship,
5087
}
5188

52-
// place SPIRE API object into result
53-
result = append(result, spireAPIFederation)
54-
}
89+
result = append(result, &resultEntry)
5590

56-
return ListFederationRelationshipsResponse{
57-
FederationRelationships: result,
91+
}
92+
return BatchCreateFederationRelationshipsResponse{
93+
Results: result,
5894
}, nil
5995
}
96+
97+

0 commit comments

Comments
 (0)