From 9de36b9d996df60a0fe81ae867c49d3bf4d2a3b0 Mon Sep 17 00:00:00 2001 From: Nicolas Braud-Santoni Date: Sun, 14 Aug 2016 01:24:40 +0200 Subject: [PATCH] admin_user: Allow relative paths to pubkeys The paths are relative to the manifest. Also, the file validation happens during the validation phase. --- bootstrapvz/plugins/admin_user/__init__.py | 8 ++--- .../plugins/admin_user/manifest-schema.yml | 6 ++-- bootstrapvz/plugins/admin_user/tasks.py | 32 ++++++++++++++++--- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/bootstrapvz/plugins/admin_user/__init__.py b/bootstrapvz/plugins/admin_user/__init__.py index 4b81c56..0627a96 100644 --- a/bootstrapvz/plugins/admin_user/__init__.py +++ b/bootstrapvz/plugins/admin_user/__init__.py @@ -1,13 +1,8 @@ - - def validate_manifest(data, validator, error): import os.path + schema_path = os.path.normpath(os.path.join(os.path.dirname(__file__), 'manifest-schema.yml')) validator(data, schema_path) - pubkey = data['plugins']['admin_user'].get('pubkey', None) - if pubkey is not None and not os.path.exists(pubkey): - msg = 'Could not find public key at %s' % pubkey - error(msg, ['plugins', 'admin_user', 'pubkey']) def resolve_tasks(taskset, manifest): @@ -24,6 +19,7 @@ def resolve_tasks(taskset, manifest): taskset.add(tasks.AdminUserPassword) if 'pubkey' in manifest.plugins['admin_user']: + taskset.add(tasks.CheckPublicKeyFile) taskset.add(tasks.AdminUserPublicKey) elif manifest.provider['name'] == 'ec2': logging.getLogger(__name__).info("The SSH key will be obtained from EC2") diff --git a/bootstrapvz/plugins/admin_user/manifest-schema.yml b/bootstrapvz/plugins/admin_user/manifest-schema.yml index 4d20396..394b5de 100644 --- a/bootstrapvz/plugins/admin_user/manifest-schema.yml +++ b/bootstrapvz/plugins/admin_user/manifest-schema.yml @@ -11,10 +11,10 @@ properties: properties: username: {type: string} password: {type: string} - pubkey: {$ref: '#/definitions/absolute_path'} + pubkey: {$ref: '#/definitions/path'} required: [username] additionalProperties: false definitions: - absolute_path: - pattern: ^/[^\0]+$ + path: + pattern: ^[^\0]+$ type: string diff --git a/bootstrapvz/plugins/admin_user/tasks.py b/bootstrapvz/plugins/admin_user/tasks.py index 583e0e5..b13bf13 100644 --- a/bootstrapvz/plugins/admin_user/tasks.py +++ b/bootstrapvz/plugins/admin_user/tasks.py @@ -8,6 +8,21 @@ import logging log = logging.getLogger(__name__) +class CheckPublicKeyFile(Task): + description = 'Check that the public key is a valid file' + phase = phases.validation + + @classmethod + def run(cls, info): + from bootstrapvz.common.tools import log_call, rel_path + + pubkey = info.manifest.plugins['admin_user'].get('pubkey', None) + if pubkey is not None: + if not os.path.isfile(rel_path(info.manifest.path, pubkey)): + msg = 'Could not find public key at %s' % pubkey + info.manifest.validation_error(msg, ['plugins', 'admin_user', 'pubkey']) + + class AddSudoPackage(Task): description = 'Adding `sudo\' to the image packages' phase = phases.preparation @@ -74,14 +89,21 @@ class AdminUserPublicKey(Task): # Get the stuff we need (username & public key) username = info.manifest.plugins['admin_user']['username'] - with open(info.manifest.plugins['admin_user']['pubkey']) as pubkey_handle: + + from bootstrapvz.common.tools import rel_path + pubkey_path = rel_path(info.manifest.path, + info.manifest.plugins['admin_user']['pubkey']) + + with open(pubkey_path) as pubkey_handle: pubkey = pubkey_handle.read() # paths - ssh_dir_rel = os.path.join('home', username, '.ssh') - auth_keys_rel = os.path.join(ssh_dir_rel, 'authorized_keys') - ssh_dir_abs = os.path.join(info.root, ssh_dir_rel) - auth_keys_abs = os.path.join(info.root, auth_keys_rel) + from os.path import join + ssh_dir_rel = join('home', username, '.ssh') + auth_keys_rel = join(ssh_dir_rel, 'authorized_keys') + ssh_dir_abs = join(info.root, ssh_dir_rel) + auth_keys_abs = join(info.root, auth_keys_rel) + # Create the ssh dir if nobody has created it yet if not os.path.exists(ssh_dir_abs): os.mkdir(ssh_dir_abs, 0700)