|
Packit Service |
a04d08 |
# Copyright (C) 2013 Yahoo! Inc.
|
|
Packit Service |
a04d08 |
# Copyright (C) 2014 Canonical, Ltd
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# Author: Joshua Harlow <harlowja@yahoo-inc.com>
|
|
Packit Service |
a04d08 |
# Author: Dustin Kirkland <kirkland@ubuntu.com>
|
|
Packit Service |
a04d08 |
# Author: Scott Moser <scott.moser@canonical.com>
|
|
Packit Service |
a04d08 |
#
|
|
Packit Service |
a04d08 |
# This file is part of cloud-init. See LICENSE file for license information.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
"""
|
|
Packit Service |
a04d08 |
Seed Random
|
|
Packit Service |
a04d08 |
-----------
|
|
Packit Service |
a04d08 |
**Summary:** provide random seed data
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
Since all cloud instances started from the same image will produce very similar
|
|
Packit Service |
a04d08 |
data when they are first booted, as they are all starting with the same seed
|
|
Packit Service |
a04d08 |
for the kernel's entropy keyring. To avoid this, random seed data can be
|
|
Packit Service |
a04d08 |
provided to the instance either as a string or by specifying a command to run
|
|
Packit Service |
a04d08 |
to generate the data.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
Configuration for this module is under the ``random_seed`` config key. The
|
|
Packit Service |
a04d08 |
``file`` key specifies the path to write the data to, defaulting to
|
|
Packit Service |
a04d08 |
``/dev/urandom``. Data can be passed in directly with ``data``, and may
|
|
Packit Service |
a04d08 |
optionally be specified in encoded form, with the encoding specified in
|
|
Packit Service |
a04d08 |
``encoding``.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
.. note::
|
|
Packit Service |
a04d08 |
when using a multiline value for ``data`` or specifying binary data, be
|
|
Packit Service |
a04d08 |
sure to follow yaml syntax and use the ``|`` and ``!binary`` yaml format
|
|
Packit Service |
a04d08 |
specifiers when appropriate
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
Instead of specifying a data string, a command can be run to generate/collect
|
|
Packit Service |
a04d08 |
the data to be written. The command should be specified as a list of args in
|
|
Packit Service |
a04d08 |
the ``command`` key. If a command is specified that cannot be run, no error
|
|
Packit Service |
a04d08 |
will be reported unless ``command_required`` is set to true.
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
For example, to use ``pollinate`` to gather data from a
|
|
Packit Service |
a04d08 |
remote entropy server and write it to ``/dev/urandom``, the following could be
|
|
Packit Service |
a04d08 |
used::
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
random_seed:
|
|
Packit Service |
a04d08 |
file: /dev/urandom
|
|
Packit Service |
a04d08 |
command: ["pollinate", "--server=http://local.polinate.server"]
|
|
Packit Service |
a04d08 |
command_required: true
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
**Internal name:** ``cc_seed_random``
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
**Module frequency:** per instance
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
**Supported distros:** all
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
**Config keys**::
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
random_seed:
|
|
Packit Service |
a04d08 |
file: <file>
|
|
Packit Service |
a04d08 |
data: <random string>
|
|
Packit Service |
a04d08 |
encoding: <raw/base64/b64/gzip/gz>
|
|
Packit Service |
a04d08 |
command: [<cmd name>, <arg1>, <arg2>...]
|
|
Packit Service |
a04d08 |
command_required: <true/false>
|
|
Packit Service |
a04d08 |
"""
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
import base64
|
|
Packit Service |
a04d08 |
import os
|
|
Packit Service |
751c4a |
from io import BytesIO
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
from cloudinit import log as logging
|
|
Packit Service |
a04d08 |
from cloudinit.settings import PER_INSTANCE
|
|
Packit Service |
751c4a |
from cloudinit import subp
|
|
Packit Service |
a04d08 |
from cloudinit import util
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
frequency = PER_INSTANCE
|
|
Packit Service |
a04d08 |
LOG = logging.getLogger(__name__)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def _decode(data, encoding=None):
|
|
Packit Service |
a04d08 |
if not data:
|
|
Packit Service |
a04d08 |
return b''
|
|
Packit Service |
a04d08 |
if not encoding or encoding.lower() in ['raw']:
|
|
Packit Service |
a04d08 |
return util.encode_text(data)
|
|
Packit Service |
a04d08 |
elif encoding.lower() in ['base64', 'b64']:
|
|
Packit Service |
a04d08 |
return base64.b64decode(data)
|
|
Packit Service |
a04d08 |
elif encoding.lower() in ['gzip', 'gz']:
|
|
Packit Service |
a04d08 |
return util.decomp_gzip(data, quiet=False, decode=None)
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
raise IOError("Unknown random_seed encoding: %s" % (encoding))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def handle_random_seed_command(command, required, env=None):
|
|
Packit Service |
a04d08 |
if not command and required:
|
|
Packit Service |
a04d08 |
raise ValueError("no command found but required=true")
|
|
Packit Service |
a04d08 |
elif not command:
|
|
Packit Service |
a04d08 |
LOG.debug("no command provided")
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
cmd = command[0]
|
|
Packit Service |
751c4a |
if not subp.which(cmd):
|
|
Packit Service |
a04d08 |
if required:
|
|
Packit Service |
a04d08 |
raise ValueError(
|
|
Packit Service |
a04d08 |
"command '{cmd}' not found but required=true".format(cmd=cmd))
|
|
Packit Service |
a04d08 |
else:
|
|
Packit Service |
a04d08 |
LOG.debug("command '%s' not found for seed_command", cmd)
|
|
Packit Service |
a04d08 |
return
|
|
Packit Service |
751c4a |
subp.subp(command, env=env, capture=False)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
def handle(name, cfg, cloud, log, _args):
|
|
Packit Service |
a04d08 |
mycfg = cfg.get('random_seed', {})
|
|
Packit Service |
a04d08 |
seed_path = mycfg.get('file', '/dev/urandom')
|
|
Packit Service |
a04d08 |
seed_data = mycfg.get('data', b'')
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
seed_buf = BytesIO()
|
|
Packit Service |
a04d08 |
if seed_data:
|
|
Packit Service |
a04d08 |
seed_buf.write(_decode(seed_data, encoding=mycfg.get('encoding')))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# 'random_seed' is set up by Azure datasource, and comes already in
|
|
Packit Service |
a04d08 |
# openstack meta_data.json
|
|
Packit Service |
a04d08 |
metadata = cloud.datasource.metadata
|
|
Packit Service |
a04d08 |
if metadata and 'random_seed' in metadata:
|
|
Packit Service |
a04d08 |
seed_buf.write(util.encode_text(metadata['random_seed']))
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
seed_data = seed_buf.getvalue()
|
|
Packit Service |
a04d08 |
if len(seed_data):
|
|
Packit Service |
a04d08 |
log.debug("%s: adding %s bytes of random seed entropy to %s", name,
|
|
Packit Service |
a04d08 |
len(seed_data), seed_path)
|
|
Packit Service |
a04d08 |
util.append_file(seed_path, seed_data)
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
command = mycfg.get('command', None)
|
|
Packit Service |
a04d08 |
req = mycfg.get('command_required', False)
|
|
Packit Service |
a04d08 |
try:
|
|
Packit Service |
a04d08 |
env = os.environ.copy()
|
|
Packit Service |
a04d08 |
env['RANDOM_SEED_FILE'] = seed_path
|
|
Packit Service |
a04d08 |
handle_random_seed_command(command=command, required=req, env=env)
|
|
Packit Service |
a04d08 |
except ValueError as e:
|
|
Packit Service |
a04d08 |
log.warning("handling random command [%s] failed: %s", command, e)
|
|
Packit Service |
a04d08 |
raise e
|
|
Packit Service |
a04d08 |
|
|
Packit Service |
a04d08 |
# vi: ts=4 expandtab
|