Client: send join request with signed message to verify validity
diff --git a/core/nebula/api/main.go b/core/nebula/api/main.go
index c0c4817..51302ad 100644
--- a/core/nebula/api/main.go
+++ b/core/nebula/api/main.go
@@ -21,7 +21,7 @@
var kubeConfig = flag.String("kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
var masterURL = flag.String("master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.")
var namespace = flag.String("namespace", "", "Namespace where Nebula CA and Node secrets are stored.")
-var caSecretName = flag.String("ca-secret-name", "", "Name of the Nebula CA secret storing certificate information.")
+var caName = flag.String("ca-name", "", "Name of the Nebula CA.")
//go:embed templates/*
var tmpls embed.FS
@@ -136,13 +136,19 @@
}
}
-type verifyReq struct {
+type joinReq struct {
Message []byte `json:"message"`
Signature []byte `json:"signature"`
+ Name string `json:"name"`
+ PublicKey []byte `json:"public_key"`
+ IPCidr string `json:"ip_cidr"`
}
-func (h *Handler) verify(w http.ResponseWriter, r *http.Request) {
- var req verifyReq
+type joinResp struct {
+}
+
+func (h *Handler) join(w http.ResponseWriter, r *http.Request) {
+ var req joinReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
@@ -156,6 +162,18 @@
http.Error(w, "Signature could not be verified", http.StatusBadRequest)
return
}
+ _, _, err = h.mgr.CreateNode(
+ *namespace,
+ req.Name,
+ *namespace,
+ *caName,
+ req.IPCidr,
+ string(req.PublicKey),
+ )
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
}
func main() {
@@ -177,7 +195,7 @@
kubeClient: kubeClient,
nebulaClient: nebulaClient,
namespace: *namespace,
- caSecretName: *caSecretName,
+ caName: *caName,
}
handler := Handler{
mgr: mgr,
@@ -186,7 +204,7 @@
r := mux.NewRouter()
r.HandleFunc("/api/ip", handler.getNextIP)
r.HandleFunc("/api/sign", handler.sign)
- r.HandleFunc("/api/verify", handler.verify)
+ r.HandleFunc("/api/join", handler.join)
r.HandleFunc("/node/{namespace:[a-zA-z0-9-]+}/{name:[a-zA-z0-9-]+}", handler.handleNode)
r.HandleFunc("/ca/{namespace:[a-zA-z0-9-]+}/{name:[a-zA-z0-9-]+}", handler.handleCA)
r.HandleFunc("/sign-node", handler.handleSignNode)
diff --git a/core/nebula/api/manager.go b/core/nebula/api/manager.go
index 40f6eeb..1b396ff 100644
--- a/core/nebula/api/manager.go
+++ b/core/nebula/api/manager.go
@@ -36,7 +36,7 @@
kubeClient kubernetes.Interface
nebulaClient clientset.Interface
namespace string
- caSecretName string
+ caName string
}
func (m *Manager) ListAll() ([]*nebulaCA, error) {
@@ -100,11 +100,7 @@
}
func (m *Manager) GetCACertQR(namespace, name string) ([]byte, error) {
- ca, err := m.nebulaClient.LekvaV1().NebulaCAs(namespace).Get(context.TODO(), name, metav1.GetOptions{})
- if err != nil {
- return nil, err
- }
- secret, err := m.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), ca.Spec.SecretName, metav1.GetOptions{})
+ secret, err := m.getCASecret(namespace, name)
if err != nil {
return nil, err
}
@@ -131,7 +127,7 @@
}
func (m *Manager) Sign(message []byte) ([]byte, error) {
- secret, err := m.kubeClient.CoreV1().Secrets(m.namespace).Get(context.TODO(), m.caSecretName, metav1.GetOptions{})
+ secret, err := m.getCASecret(m.namespace, m.caName)
if err != nil {
return nil, err
}
@@ -143,7 +139,7 @@
}
func (m *Manager) VerifySignature(message, signature []byte) (bool, error) {
- secret, err := m.kubeClient.CoreV1().Secrets(m.namespace).Get(context.TODO(), m.caSecretName, metav1.GetOptions{})
+ secret, err := m.getCASecret(m.namespace, m.caName)
if err != nil {
return false, err
}
@@ -154,6 +150,14 @@
return ed25519.Verify(edPriv.Public().(ed25519.PublicKey), message, signature), nil
}
+func (m *Manager) getCASecret(namespace, name string) (*corev1.Secret, error) {
+ ca, err := m.nebulaClient.LekvaV1().NebulaCAs(namespace).Get(context.TODO(), name, metav1.GetOptions{})
+ if err != nil {
+ return nil, err
+ }
+ return m.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), ca.Spec.SecretName, metav1.GetOptions{})
+}
+
func (m *Manager) getNodeSecret(namespace, name string) (*corev1.Secret, error) {
node, err := m.nebulaClient.LekvaV1().NebulaNodes(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {