Implement authentication via Keystone

This commit is contained in:
Dmitry Tantsur 2014-10-09 16:45:43 +02:00
parent fdd0ef4124
commit 74242c2776
6 changed files with 30 additions and 5 deletions

View File

@ -40,11 +40,12 @@ HTTP API consist of 2 endpoints:
* ``/v1/discover`` initiate hardware discovery. Request body: JSON - list of
UUID's of nodes to discover. All power management configuration for these nodes
needs to be done prior to calling the endpoint.
needs to be done prior to calling the endpoint. Requires X-Auth-Token header
with Keystone token for authentication.
.. note::
Right now this endpoint is not authenticated. It will switch to
OpenStack authentication in the near future.
Before version 0.2.0 this endpoint was not authenticated.
Now it is, but check for admin role is not implemented yet.
* ``/v1/continue`` internal endpoint for the discovery ramdisk to post back
discovered data. Should not be used for anything other than implementing

View File

@ -17,6 +17,9 @@
;listen_address = 0.0.0.0
; Port to listen on.
;listen_port = 5050
; Whether to authenticate with Keystone on discovery initialization endpoint.
; Note that discovery postback endpoint is never authenticated.
;authenticate = true
; Debug mode enabled/disabled.
;debug = false

View File

@ -4,6 +4,7 @@ import sys
import eventlet
from flask import Flask, request
from keystoneclient import exceptions
from ironic_discoverd import discoverd
@ -24,6 +25,17 @@ def post_continue():
@app.route('/v1/discover', methods=['POST'])
def post_discover():
if discoverd.CONF.getboolean('discoverd', 'authenticate'):
if not request.headers.get('X-Auth-Token'):
LOG.debug("No X-Auth-Token header, rejecting")
return 'Authentication required', 401
try:
discoverd.get_keystone(token=request.headers['X-Auth-Token'])
except exceptions.Unauthorized:
LOG.debug("Keystone denied access, rejecting")
return 'Access denied', 403
# TODO(dtanstur): check for admin role
data = request.get_json(force=True)
LOG.debug("Got JSON %s, going into processing thread", data)
eventlet.greenthread.spawn_n(discoverd.discover, data)

View File

@ -4,6 +4,7 @@ import re
from subprocess import call, check_call
from ironicclient import client, exceptions
from keystoneclient.v2_0 import client as keystone
LOG = logging.getLogger("discoverd")
@ -12,7 +13,8 @@ CONF = ConfigParser.ConfigParser(
defaults={'debug': 'false',
'listen_address': '0.0.0.0',
'listen_port': '5050',
'dnsmasq_interface': 'br-ctlplane'})
'dnsmasq_interface': 'br-ctlplane',
'authenticate': 'true'})
OS_ARGS = ('os_password', 'os_username', 'os_auth_url', 'os_tenant_name')
@ -21,6 +23,11 @@ def get_client():
return client.get_client(1, **args)
def get_keystone(token):
return keystone.Client(token=token, auth_url=CONF.get('discoverd',
'os_auth_url'))
def is_valid_mac(address):
m = "[0-9a-f]{2}(:[0-9a-f]{2}){5}$"
return (isinstance(address, (str, unicode))

View File

@ -1,3 +1,4 @@
Flask>=0.10,<1.0
python-ironicclient>=0.2.1
eventlet>=0.15.1
python-keystoneclient>=0.10.0

View File

@ -9,6 +9,7 @@ setup(
author_email = "dtansur@redhat.com",
url = "https://github.com/Divius/ironic-discoverd/",
packages=['ironic_discoverd'],
install_requires = ['Flask', 'python-ironicclient', 'eventlet'],
install_requires = ['Flask', 'python-ironicclient', 'eventlet',
'python-keystoneclient'],
scripts = ['bin/ironic-discoverd'],
)