179 lines
6.4 KiB
Go
179 lines
6.4 KiB
Go
package nodeagent
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
clustermodule "github.com/example/remote-access-platform/backend/internal/modules/cluster"
|
|
"github.com/example/remote-access-platform/backend/internal/platform/httpx"
|
|
"github.com/example/remote-access-platform/backend/internal/platform/module"
|
|
"github.com/example/remote-access-platform/backend/internal/platform/secrets"
|
|
)
|
|
|
|
type Module struct {
|
|
cluster *clustermodule.Service
|
|
}
|
|
|
|
func NewModule(deps module.Dependencies) *Module {
|
|
clusterStore := clustermodule.NewPostgresStore(deps.Infra.DB)
|
|
if deps.Config.Secret.EncryptionKeyBase64 != "" {
|
|
if encryptor, err := secrets.NewEncryptor(deps.Config.Secret.EncryptionKeyBase64, deps.Config.Secret.EncryptionKeyID); err == nil {
|
|
clusterStore.WithClusterKeyEncryptor(encryptor)
|
|
}
|
|
}
|
|
return &Module{
|
|
cluster: clustermodule.NewService(clusterStore),
|
|
}
|
|
}
|
|
|
|
func (m *Module) Name() string {
|
|
return "nodeagent"
|
|
}
|
|
|
|
func (m *Module) RegisterRoutes(router chi.Router) {
|
|
router.Route("/node-agents", func(r chi.Router) {
|
|
r.Post("/docker-join-bundle", m.dockerJoinBundle)
|
|
r.Post("/windows-join-bundle", m.windowsJoinBundle)
|
|
r.Post("/linux-join-bundle", m.linuxJoinBundle)
|
|
r.Post("/register", m.registerFabricNode)
|
|
r.Post("/enroll", m.enrollAgent)
|
|
r.Post("/enrollments/{requestID}/join", m.fetchEnrollmentJoinContract)
|
|
})
|
|
}
|
|
|
|
func (m *Module) linuxJoinBundle(w http.ResponseWriter, r *http.Request) {
|
|
var payload clustermodule.DockerInstallProfileRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, "invalid linux join bundle payload")
|
|
return
|
|
}
|
|
bundle, err := m.cluster.GetLinuxJoinBundle(r.Context(), payload)
|
|
if err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
httpx.WriteJSON(w, http.StatusOK, map[string]any{"join_bundle": bundle})
|
|
}
|
|
|
|
func (m *Module) windowsJoinBundle(w http.ResponseWriter, r *http.Request) {
|
|
var payload clustermodule.DockerInstallProfileRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, "invalid windows join bundle payload")
|
|
return
|
|
}
|
|
bundle, err := m.cluster.GetWindowsJoinBundle(r.Context(), payload)
|
|
if err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
httpx.WriteJSON(w, http.StatusOK, map[string]any{"join_bundle": bundle})
|
|
}
|
|
|
|
func (m *Module) dockerJoinBundle(w http.ResponseWriter, r *http.Request) {
|
|
var payload clustermodule.DockerInstallProfileRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, "invalid docker join bundle payload")
|
|
return
|
|
}
|
|
bundle, err := m.cluster.GetDockerJoinBundle(r.Context(), payload)
|
|
if err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
httpx.WriteJSON(w, http.StatusOK, map[string]any{"join_bundle": bundle})
|
|
}
|
|
|
|
func (m *Module) registerFabricNode(w http.ResponseWriter, r *http.Request) {
|
|
var payload struct {
|
|
ClusterID string `json:"cluster_id"`
|
|
NodeKey string `json:"node_key"`
|
|
Name string `json:"name"`
|
|
OwnershipType string `json:"ownership_type"`
|
|
OwnerOrganizationID *string `json:"owner_organization_id"`
|
|
ReportedVersion *string `json:"reported_version"`
|
|
Metadata json.RawMessage `json:"metadata"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, "invalid fabric node registration payload")
|
|
return
|
|
}
|
|
item, err := m.cluster.RegisterFabricNode(r.Context(), clustermodule.RegisterFabricNodeInput{
|
|
ClusterID: payload.ClusterID,
|
|
NodeKey: payload.NodeKey,
|
|
Name: payload.Name,
|
|
OwnershipType: payload.OwnershipType,
|
|
OwnerOrganizationID: payload.OwnerOrganizationID,
|
|
ReportedVersion: payload.ReportedVersion,
|
|
Metadata: payload.Metadata,
|
|
})
|
|
if err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
httpx.WriteJSON(w, http.StatusOK, map[string]any{
|
|
"status": "registered",
|
|
"node_id": item.ID,
|
|
"node": item,
|
|
})
|
|
}
|
|
|
|
func (m *Module) enrollAgent(w http.ResponseWriter, r *http.Request) {
|
|
var payload struct {
|
|
ClusterID string `json:"cluster_id"`
|
|
JoinToken string `json:"join_token"`
|
|
NodeName string `json:"node_name"`
|
|
NodeFingerprint string `json:"node_fingerprint"`
|
|
PublicKey string `json:"public_key"`
|
|
ReportedCapabilities json.RawMessage `json:"reported_capabilities"`
|
|
ReportedFacts json.RawMessage `json:"reported_facts"`
|
|
RequestedRoles json.RawMessage `json:"requested_roles"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, "invalid agent enrollment payload")
|
|
return
|
|
}
|
|
joinRequest, err := m.cluster.CreateJoinRequest(r.Context(), clustermodule.CreateJoinRequestInput{
|
|
ClusterID: payload.ClusterID,
|
|
JoinToken: payload.JoinToken,
|
|
NodeName: payload.NodeName,
|
|
NodeFingerprint: payload.NodeFingerprint,
|
|
PublicKey: payload.PublicKey,
|
|
ReportedCapabilities: payload.ReportedCapabilities,
|
|
ReportedFacts: payload.ReportedFacts,
|
|
RequestedRoles: payload.RequestedRoles,
|
|
})
|
|
if err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
httpx.WriteJSON(w, http.StatusAccepted, map[string]any{
|
|
"status": "pending_approval",
|
|
"join_request": joinRequest,
|
|
})
|
|
}
|
|
|
|
func (m *Module) fetchEnrollmentJoinContract(w http.ResponseWriter, r *http.Request) {
|
|
var payload struct {
|
|
ClusterID string `json:"cluster_id"`
|
|
NodeFingerprint string `json:"node_fingerprint"`
|
|
PublicKey string `json:"public_key"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, "invalid enrollment join payload")
|
|
return
|
|
}
|
|
result, err := m.cluster.GetJoinRequestJoin(r.Context(), clustermodule.GetJoinRequestJoinInput{
|
|
ClusterID: payload.ClusterID,
|
|
JoinRequestID: chi.URLParam(r, "requestID"),
|
|
NodeFingerprint: payload.NodeFingerprint,
|
|
PublicKey: payload.PublicKey,
|
|
})
|
|
if err != nil {
|
|
httpx.WriteError(w, http.StatusBadRequest, err.Error())
|
|
return
|
|
}
|
|
httpx.WriteJSON(w, http.StatusOK, result)
|
|
}
|