Commit 7e2413ec authored by Alain Takoudjou's avatar Alain Takoudjou

slapos: update client to use caucase when requesting certificate

parent 3bc07695
...@@ -56,6 +56,7 @@ setup(name=name, ...@@ -56,6 +56,7 @@ setup(name=name,
'cliff', 'cliff',
'requests>=2.4.3', 'requests>=2.4.3',
'six', 'six',
'caucase', # used to manage ca client request
'uritemplate', # used by hateoas navigator 'uritemplate', # used by hateoas navigator
] + additional_install_requires, ] + additional_install_requires,
extras_require={ extras_require={
......
...@@ -32,6 +32,7 @@ import os ...@@ -32,6 +32,7 @@ import os
import sys import sys
import requests import requests
from caucase.cli_flask import CertificateAuthorityRequest
from slapos.cli.config import ClientConfigCommand from slapos.cli.config import ClientConfigCommand
from slapos.util import mkdir_p, parse_certificate_key_pair from slapos.util import mkdir_p, parse_certificate_key_pair
...@@ -59,19 +60,27 @@ class ConfigureClientCommand(ClientConfigCommand): ...@@ -59,19 +60,27 @@ class ConfigureClientCommand(ClientConfigCommand):
help="SlapOS 'credential security' authentication token " help="SlapOS 'credential security' authentication token "
"(use '--token ask' for interactive prompt)") "(use '--token ask' for interactive prompt)")
ap.add_argument('--login',
help="Your username on SlapOS Master web")
return ap return ap
def take_action(self, args): def take_action(self, args):
if not args.login:
parser.error('Please enter your username on SlapOS Master Web. Use --login LOGIN')
parser.print_help()
return
do_configure_client(logger=self.app.log, do_configure_client(logger=self.app.log,
master_url_web=args.master_url_web, master_url_web=args.master_url_web,
token=args.token, token=args.token,
config_path=self.config_path(args), config_path=self.config_path(args),
master_url=args.master_url) master_url=args.master_url,
login=args.login)
def sign_certificate(logger, master_url_web, csr, token):
def get_certificate_key_pair(logger, master_url_web, token):
req = requests.post('/'.join([master_url_web, 'myspace/my_account/request-a-certificate/WebSection_requestNewCertificate']), req = requests.post('/'.join([master_url_web, 'myspace/my_account/request-a-certificate/WebSection_requestNewCertificate']),
data={}, data={'certificate_signature_request': csr},
headers={'X-Access-Token': token}, headers={'X-Access-Token': token},
verify=False) verify=False)
...@@ -82,17 +91,17 @@ def get_certificate_key_pair(logger, master_url_web, token): ...@@ -82,17 +91,17 @@ def get_certificate_key_pair(logger, master_url_web, token):
req.raise_for_status() req.raise_for_status()
return parse_certificate_key_pair(req.text) return parse_certificate_from_html(req.text)
def fetch_configuration_template(): def fetch_configuration_template():
# XXX: change to local version. # XXX: change to local version.
req = requests.get('http://git.erp5.org/gitweb/slapos.core.git/blob_plain/HEAD:/slapos-client.cfg.example') req = requests.get('https://lab.nexedi.com/nexedi/slapos.core/raw/master/slapos-client.cfg.example')
req.raise_for_status() req.raise_for_status()
return req.text return req.text
def do_configure_client(logger, master_url_web, token, config_path, master_url): def do_configure_client(logger, master_url_web, token, config_path, master_url, login):
while not token: while not token:
token = raw_input('Credential security token: ').strip() token = raw_input('Credential security token: ').strip()
...@@ -111,16 +120,29 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url): ...@@ -111,16 +120,29 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url):
cert_path = os.path.join(basedir, 'client.crt') cert_path = os.path.join(basedir, 'client.crt')
if os.path.exists(cert_path): if os.path.exists(cert_path):
logger.critical('There is a file in %s. ' logger.critical('There is a certificate in %s. '
'Please remove it before creating a new certificate.', cert_path) 'Please remove it before creating a new certificate.', cert_path)
sys.exit(1) sys.exit(1)
key_path = os.path.join(basedir, 'client.key') key_path = os.path.join(basedir, 'client.key')
if os.path.exists(key_path): if os.path.exists(key_path):
logger.critical('There is a file in %s. ' logger.critical('There is a key in %s. '
'Please remove it before creating a new key.', key_path) 'Please remove it before creating a new key.', key_path)
sys.exit(1) sys.exit(1)
ca_cert_path = os.path.join(basedir, 'ca.crt')
# create certificate authority client
ca_client = CertificateAuthorityRequest(
key_path,
cert_path,
ca_cert_path,
ca_url='')
logger.debug('Generating key to %s', key_path)
ca_client.generatePrivatekey(key_path, size=2048)
csr_string = ca_client.generateCertificateRequest(key_path, cn=login)
# retrieve a template for the configuration file # retrieve a template for the configuration file
cfg = fetch_configuration_template() cfg = fetch_configuration_template()
...@@ -131,7 +153,7 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url): ...@@ -131,7 +153,7 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url):
# retrieve and parse the certicate and key # retrieve and parse the certicate and key
certificate, key = get_certificate_key_pair(logger, master_url_web, token) certificate = sign_certificate(logger, master_url_web, csr_string, token)
# write everything # write everything
...@@ -143,8 +165,4 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url): ...@@ -143,8 +165,4 @@ def do_configure_client(logger, master_url_web, token, config_path, master_url):
logger.debug('Writing certificate to %s', cert_path) logger.debug('Writing certificate to %s', cert_path)
fout.write(certificate) fout.write(certificate)
with os.fdopen(os.open(key_path, os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0o600), 'w') as fout:
logger.debug('Writing key to %s', key_path)
fout.write(key)
logger.info('SlapOS client configuration written to %s', config_path) logger.info('SlapOS client configuration written to %s', config_path)
...@@ -1003,6 +1003,7 @@ class HateoasNavigator(object): ...@@ -1003,6 +1003,7 @@ class HateoasNavigator(object):
return json.loads(self.GET(person_url)) return json.loads(self.GET(person_url))
class SlapHateoasNavigator(HateoasNavigator): class SlapHateoasNavigator(HateoasNavigator):
def _hateoas_getHostingSubscriptionDict(self): def _hateoas_getHostingSubscriptionDict(self):
action_object_slap_list = self.getMeDocument()['_links']['action_object_slap'] action_object_slap_list = self.getMeDocument()['_links']['action_object_slap']
for action in action_object_slap_list: for action in action_object_slap_list:
...@@ -1079,3 +1080,19 @@ class SlapHateoasNavigator(HateoasNavigator): ...@@ -1079,3 +1080,19 @@ class SlapHateoasNavigator(HateoasNavigator):
instance_url = self.hateoasGetLinkFromLinks(instance_list, reference) instance_url = self.hateoasGetLinkFromLinks(instance_list, reference)
instance = self._hateoasGetInformation(instance_url) instance = self._hateoasGetInformation(instance_url)
return instance return instance
def getPersonReference(self):
"""
Get Some information about the current user (Person)
"""
person = getMeDocument()
portal_type = person['_links']['type'].get('name')
if not portal_type == "Person":
return {}
# Get Information on Person assignment
person_relative_url = self.getRelativeUrlFromUrn(
person['_embedded']['_view']['_links']['traversed_document']['href'])
return self.getDocumentAndHateoas(
person_relative_url, view='assignment'
)['_embedded']['_view']['my_reference']['default']
...@@ -60,20 +60,16 @@ def chownDirectory(path, uid, gid): ...@@ -60,20 +60,16 @@ def chownDirectory(path, uid, gid):
]) ])
def parse_certificate_key_pair(html): def parse_certificate_from_html(html):
""" """
Extract (certificate, key) pair from an HTML page received by SlapOS Master. Extract certificate from an HTML page received by SlapOS Master.
""" """
c_start = html.find("Certificate:") c_start = html.find("Certificate:")
c_end = html.find("</textarea>", c_start) c_end = html.find("</textarea>", c_start)
certificate = html[c_start:c_end] certificate = html[c_start:c_end]
k_start = html.find("-----BEGIN PRIVATE KEY-----") return certificate
k_end = html.find("</textarea>", k_start)
key = html[k_start:k_end]
return certificate, key
def string_to_boolean(string): def string_to_boolean(string):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment