From 0eac79ba01c67dd4a1edd89e2805e6c835cc067e Mon Sep 17 00:00:00 2001 From: Marco Mariani <marco.mariani@nexedi.com> Date: Fri, 14 Jun 2013 15:59:59 +0200 Subject: [PATCH] --token support for 'slapos node register' --- slapos/cli/register.py | 6 ++- slapos/register/register.py | 81 +++++++++++++++++++++---------------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/slapos/cli/register.py b/slapos/cli/register.py index e5f5559b2e..d6f8250c41 100644 --- a/slapos/cli/register.py +++ b/slapos/cli/register.py @@ -60,8 +60,11 @@ class RegisterCommand(Command): 'asks it interactively. NOTE: giving password as parameter ' 'should be avoided for security reasons.') + ap.add_argument('--token', + help="SlapOS Master authentication token " + "(use '--token ask' for interactive prompt)") + ap.add_argument('-t', '--create-tap', - default=False, action='store_true', help='Will trigger creation of one virtual "tap" interface per ' 'Partition and attach it to primary interface. Requires ' @@ -70,7 +73,6 @@ class RegisterCommand(Command): ' (default: %(default)s)') ap.add_argument('-n', '--dry-run', - default=False, action='store_true', help='Simulate the execution steps' ' (default: %(default)s)') diff --git a/slapos/register/register.py b/slapos/register/register.py index 1bb2dd824d..650c3148f2 100644 --- a/slapos/register/register.py +++ b/slapos/register/register.py @@ -37,45 +37,48 @@ import shutil import stat import sys import tempfile -import urllib2 import subprocess from subprocess import CalledProcessError - -def authenticate(request, login, password): - auth = '%s:%s' % (login, password) - authheader = 'Basic %s' % auth.encode('base64').rstrip() - request.add_header('Authorization', authheader) +import requests def check_credentials(url, login, password): - """Check if logged correctly on SlapOS Master""" - request = urllib2.Request(url) - authenticate(request, login, password) - return 'Logout' in urllib2.urlopen(request).read() + """Check if login and password are correct""" + req = requests.get(url, auth=(login, password), verify=False) + return 'Logout' in req.text -def get_certificates(master_url_web, node_name, login, password, logger): +def get_certificates(logger, master_url_web, node_name, token=None, login=None, password=None): """Download certificates from SlapOS Master""" - register_server_url = '/'.join([master_url_web, ("add-a-server/WebSection_registerNewComputer?dialog_id=WebSection_viewServerInformationDialog&dialog_method=WebSection_registerNewComputer&title={}&object_path=/erp5/web_site_module/hosting/add-a-server&update_method=&cancel_url=https%3A//www.vifib.net/add-a-server/WebSection_viewServerInformationDialog&Base_callDialogMethod=&field_your_title=Essai1&dialog_category=None&form_id=view".format(node_name))]) - request = urllib2.Request(register_server_url) - authenticate(request, login, password) - try: - req = urllib2.urlopen(request) - except urllib2.HTTPError as exc: + if token: + req = requests.post('/'.join([master_url_web, 'add-a-server/WebSection_registerNewComputer']), + data={'title': node_name}, + headers={'X-Access-Token': token}, + verify=False) + else: + register_server_url = '/'.join([master_url_web, ("add-a-server/WebSection_registerNewComputer?dialog_id=WebSection_viewServerInformationDialog&dialog_method=WebSection_registerNewComputer&title={}&object_path=/erp5/web_site_module/hosting/add-a-server&update_method=&cancel_url=https%3A//www.vifib.net/add-a-server/WebSection_viewServerInformationDialog&Base_callDialogMethod=&field_your_title=Essai1&dialog_category=None&form_id=view".format(node_name))]) + req = requests.get(register_server_url, auth=(login, password), verify=False) + + if not req.ok and 'Certificate still active.' in req.text: # raise a readable exception if the computer name is already used, # instead of an opaque 500 Internal Error. # this will not work with the new API. - if exc.getcode() == 500: - error_body = exc.read() - if 'Certificate still active.' in error_body: - logger.error('The node name "%s" is already in use. Please change the name, or revoke the active certificate if you want to replace the node.' % node_name) - sys.exit(1) - raise + logger.error('The node name "%s" is already in use. Please change the name, or revoke the active certificate if you want to replace the node.' % node_name) + sys.exit(1) - return req.read() + if req.status_code == 403: + if token: + msg = 'Please check the authentication token or require a new one.' + else: + msg = 'Please check username and password.' + logger.error('Access denied to the SlapOS Master. %s', msg) + sys.exit(1) + else: + req.raise_for_status() + return req.text def parse_certificates(source): @@ -120,11 +123,10 @@ def get_slapos_conf_example(): """ Get slapos.cfg.example and return its path """ - request = urllib2.Request('http://git.erp5.org/gitweb/slapos.core.git/blob_plain/HEAD:/slapos.cfg.example') - req = urllib2.urlopen(request) _, path = tempfile.mkstemp() - with open(path, 'w') as fout: - fout.write(req.read()) + with open(path, 'wb') as fout: + req = requests.get('http://git.erp5.org/gitweb/slapos.core.git/blob_plain/HEAD:/slapos.cfg.example') + fout.write(req.content) return path @@ -253,15 +255,24 @@ def gen_auth(conf): def do_register(conf): """Register new computer on SlapOS Master and generate slapos.cfg""" - for login, password in gen_auth(conf): - if check_credentials(conf.master_url_web, login, password): - break - conf.logger.warning('Wrong login/password') + if conf.token == 'ask': + while True: + conf.token = raw_input('SlapOS Token: ').strip() + if conf.token: + break + + if conf.token: + certificate_key = get_certificates(conf.logger, conf.master_url_web, conf.node_name, token=conf.token) else: - return 1 + for login, password in gen_auth(conf): + if check_credentials(conf.master_url_web, login, password): + break + conf.logger.warning('Wrong login/password') + else: + return 1 + + certificate_key = get_certificates(conf.logger, conf.master_url_web, conf.node_name, login=login, password=password) - # Get source code of page having certificate and key - certificate_key = get_certificates(conf.master_url_web, conf.node_name, login, password, conf.logger) # Parse certificate and key and get computer id certificate, key = parse_certificates(certificate_key) COMP = get_computer_name(certificate) -- 2.30.9