Implement authentication via Keystone
This commit is contained in:
parent
fdd0ef4124
commit
74242c2776
|
@ -40,11 +40,12 @@ HTTP API consist of 2 endpoints:
|
||||||
|
|
||||||
* ``/v1/discover`` initiate hardware discovery. Request body: JSON - list of
|
* ``/v1/discover`` initiate hardware discovery. Request body: JSON - list of
|
||||||
UUID's of nodes to discover. All power management configuration for these nodes
|
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::
|
.. note::
|
||||||
Right now this endpoint is not authenticated. It will switch to
|
Before version 0.2.0 this endpoint was not authenticated.
|
||||||
OpenStack authentication in the near future.
|
Now it is, but check for admin role is not implemented yet.
|
||||||
|
|
||||||
* ``/v1/continue`` internal endpoint for the discovery ramdisk to post back
|
* ``/v1/continue`` internal endpoint for the discovery ramdisk to post back
|
||||||
discovered data. Should not be used for anything other than implementing
|
discovered data. Should not be used for anything other than implementing
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
;listen_address = 0.0.0.0
|
;listen_address = 0.0.0.0
|
||||||
; Port to listen on.
|
; Port to listen on.
|
||||||
;listen_port = 5050
|
;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 mode enabled/disabled.
|
||||||
;debug = false
|
;debug = false
|
||||||
|
|
|
@ -4,6 +4,7 @@ import sys
|
||||||
import eventlet
|
import eventlet
|
||||||
from flask import Flask, request
|
from flask import Flask, request
|
||||||
|
|
||||||
|
from keystoneclient import exceptions
|
||||||
|
|
||||||
from ironic_discoverd import discoverd
|
from ironic_discoverd import discoverd
|
||||||
|
|
||||||
|
@ -24,6 +25,17 @@ def post_continue():
|
||||||
|
|
||||||
@app.route('/v1/discover', methods=['POST'])
|
@app.route('/v1/discover', methods=['POST'])
|
||||||
def post_discover():
|
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)
|
data = request.get_json(force=True)
|
||||||
LOG.debug("Got JSON %s, going into processing thread", data)
|
LOG.debug("Got JSON %s, going into processing thread", data)
|
||||||
eventlet.greenthread.spawn_n(discoverd.discover, data)
|
eventlet.greenthread.spawn_n(discoverd.discover, data)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import re
|
||||||
from subprocess import call, check_call
|
from subprocess import call, check_call
|
||||||
|
|
||||||
from ironicclient import client, exceptions
|
from ironicclient import client, exceptions
|
||||||
|
from keystoneclient.v2_0 import client as keystone
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger("discoverd")
|
LOG = logging.getLogger("discoverd")
|
||||||
|
@ -12,7 +13,8 @@ CONF = ConfigParser.ConfigParser(
|
||||||
defaults={'debug': 'false',
|
defaults={'debug': 'false',
|
||||||
'listen_address': '0.0.0.0',
|
'listen_address': '0.0.0.0',
|
||||||
'listen_port': '5050',
|
'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')
|
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)
|
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):
|
def is_valid_mac(address):
|
||||||
m = "[0-9a-f]{2}(:[0-9a-f]{2}){5}$"
|
m = "[0-9a-f]{2}(:[0-9a-f]{2}){5}$"
|
||||||
return (isinstance(address, (str, unicode))
|
return (isinstance(address, (str, unicode))
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
Flask>=0.10,<1.0
|
Flask>=0.10,<1.0
|
||||||
python-ironicclient>=0.2.1
|
python-ironicclient>=0.2.1
|
||||||
eventlet>=0.15.1
|
eventlet>=0.15.1
|
||||||
|
python-keystoneclient>=0.10.0
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -9,6 +9,7 @@ setup(
|
||||||
author_email = "dtansur@redhat.com",
|
author_email = "dtansur@redhat.com",
|
||||||
url = "https://github.com/Divius/ironic-discoverd/",
|
url = "https://github.com/Divius/ironic-discoverd/",
|
||||||
packages=['ironic_discoverd'],
|
packages=['ironic_discoverd'],
|
||||||
install_requires = ['Flask', 'python-ironicclient', 'eventlet'],
|
install_requires = ['Flask', 'python-ironicclient', 'eventlet',
|
||||||
|
'python-keystoneclient'],
|
||||||
scripts = ['bin/ironic-discoverd'],
|
scripts = ['bin/ironic-discoverd'],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue