vpn client + api: add feature to approve one device from another
diff --git a/core/nebula/api/manager.go b/core/nebula/api/manager.go
index 790a01e..962b3b7 100644
--- a/core/nebula/api/manager.go
+++ b/core/nebula/api/manager.go
@@ -5,11 +5,11 @@
 	"crypto"
 	"crypto/ed25519"
 	"crypto/rand"
-	"errors"
+	"crypto/rsa"
+	"crypto/x509"
+	"encoding/base64"
 	"fmt"
 
-	"inet.af/netaddr"
-
 	"github.com/jinzhu/copier"
 	"github.com/slackhq/nebula/cert"
 
@@ -72,7 +72,7 @@
 	return ret, nil
 }
 
-func (m *Manager) CreateNode(namespace, name, caNamespace, caName, ipCidr, pubKey string) (string, string, error) {
+func (m *Manager) CreateNode(namespace, name, caNamespace, caName, ipCidr, pubKey string, encPubKey []byte) (string, string, error) {
 	node := &nebulav1.NebulaNode{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:      name,
@@ -86,6 +86,9 @@
 			SecretName:  fmt.Sprintf("%s-cert", name),
 		},
 	}
+	if encPubKey != nil {
+		node.Spec.EncPubKey = base64.StdEncoding.EncodeToString(encPubKey)
+	}
 	node, err := m.nebulaClient.LekvaV1().NebulaNodes(namespace).Create(context.TODO(), node, metav1.CreateOptions{})
 	if err != nil {
 		return "", "", err
@@ -128,25 +131,6 @@
 	return secret.Data["ca.png"], nil
 }
 
-func (m *Manager) getNextIP() (netaddr.IP, error) {
-	nodes, err := m.nebulaClient.LekvaV1().NebulaNodes(m.namespace).List(context.TODO(), metav1.ListOptions{})
-	if err != nil {
-		return netaddr.IP{}, err
-	}
-	var max netaddr.IP
-	for _, node := range nodes.Items {
-		ip := netaddr.MustParseIPPrefix(node.Spec.IPCidr)
-		if max.Less(ip.IP()) {
-			max = ip.IP()
-		}
-	}
-	n := max.Next()
-	if n.IsZero() {
-		return n, errors.New("IP address range exhausted")
-	}
-	return n, nil
-}
-
 func (m *Manager) Sign(message []byte) ([]byte, error) {
 	secret, err := m.getCASecret(m.namespace, m.caName)
 	if err != nil {
@@ -186,3 +170,15 @@
 	}
 	return m.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(), node.Spec.SecretName, metav1.GetOptions{})
 }
+
+func (m *Manager) GetNodeEncryptionPublicKey(namespace, name string) (*rsa.PublicKey, error) {
+	node, err := m.nebulaClient.LekvaV1().NebulaNodes(namespace).Get(context.TODO(), name, metav1.GetOptions{})
+	if err != nil {
+		return nil, err
+	}
+	k, err := base64.StdEncoding.DecodeString(node.Spec.EncPubKey)
+	if err != nil {
+		return nil, err
+	}
+	return x509.ParsePKCS1PublicKey(k)
+}