add an API endpoint for registering nodes
diff --git a/api/pages/node/register.py b/api/pages/node/register.py
new file mode 100644
index 0000000..f9dd958
--- /dev/null
+++ b/api/pages/node/register.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+########################################################################
+# OPENAPI-URI: /api/node/register
+########################################################################
+# post:
+#   requestBody:
+#     content:
+#       application/json:
+#         schema:
+#           $ref: '#/components/schemas/NodeCredentials'
+#     description: Node credentials
+#     required: true
+#   responses:
+#     '200':
+#       content:
+#         application/json:
+#           schema:
+#             $ref: '#/components/schemas/APIKeyResult'
+#       description: Node successfully registered with server
+#     default:
+#       content:
+#         application/json:
+#           schema:
+#             $ref: '#/components/schemas/Error'
+#       description: unexpected error
+#   summary: Registers a new node with the Warble server
+# 
+########################################################################
+
+
+
+
+
+"""
+This is the node registration handler for Apache Warble
+"""
+
+import json
+import re
+import time
+import plugins.crypto
+import plugins.registry
+import base64
+
+def run(API, environ, indata, session):
+    
+    method = environ['REQUEST_METHOD']
+    
+    # Registering a new node?
+    if method == "POST":
+        hostname = indata['hostname']
+        pubkey_pem = indata['pubkey']
+        nodeversion = indata['version'] # TODO: Check for incompatibilities!
+        
+        # Try loading the PEM
+        try:
+            pubkey = plugins.crypto.loads(pubkey_pem)
+        except:
+            raise API.exception(400, "Bad PEM payload passed from client!")
+        
+        # Okay, we have what we need for now. Register potential node and gen an API key
+        node = plugins.registry.node(session)
+        node.hostname = hostname
+        node.pem = pubkey_pem
+        node.version = nodeversion
+        node.ip = environ.get('REMOTE_ADDR', '0.0.0.0')
+        
+        # Encrypt API key with the pub key we just got. base64 encode the result
+        apikey_crypt = str(base64.b64encode(plugins.crypto.encrypt(pubkey, node.apikey)), 'ascii')
+        node.save()
+        
+        yield json.dumps({"encrypted": True, "key": apikey_crypt}, indent = 2)
+        return
+
+    
+    # Finally, if we hit a method we don't know, balk!
+    yield API.exception(400, "I don't know this request method!!")
+    
diff --git a/api/yaml/openapi/components/schemas/APIKeyResult.yaml b/api/yaml/openapi/components/schemas/APIKeyResult.yaml
new file mode 100644
index 0000000..ef65532
--- /dev/null
+++ b/api/yaml/openapi/components/schemas/APIKeyResult.yaml
@@ -0,0 +1,16 @@
+########################################################################
+# APIKeyResult                                                         #
+########################################################################
+properties:
+  encrypted:
+    description: Whether the API Key is encrypted (in case of nodes/agents requesting it)
+    example: false
+    type: boolean
+  key:
+    description: The (encrypted?) API Key assigned by the server
+    type: string
+    example: abcdef-1234
+required:
+- encrypted
+- key
+
diff --git a/api/yaml/openapi/components/schemas/NodeCredentials.yaml b/api/yaml/openapi/components/schemas/NodeCredentials.yaml
new file mode 100644
index 0000000..d4e47fe
--- /dev/null
+++ b/api/yaml/openapi/components/schemas/NodeCredentials.yaml
@@ -0,0 +1,20 @@
+########################################################################
+# NodeCredentials                                                      #
+########################################################################
+properties:
+  hostname:
+    description: The node's own perceived hostname
+    example: foo1.warble.xyz
+    type: string
+  pubkey:
+    description: The node's self-generated public RSA key, PEM-encoded
+    type: string
+  version:
+    description: The version of Warble the node is running
+    type: string
+    example: 0.1.0
+required:
+  - hostname
+  - pubkey
+  - version
+