示例#1
0
def dpkg_install(paths, check=True):
    if not hasattr(paths, 'keys'):
        pkgs = {}

        # determine package names from filenames. ideally, we would open the
        # package here and check
        for p in paths:
            fn = os.path.basename(p)
            try:
                name, version, tail = fn.split('_', 3)
                pkgs[(name, version)] = p
            except ValueError:
                raise ValueError(
                    'Could not determine package version from '
                    'package filename {}. Please rename the .deb '
                    'to standard debian convention '
                    '(name_version_arch.deb) or supply a specific '
                    'version by passing a dictionary parameter.'.format(fn))

    # log names
    log.debug('Package names: ' + ', '.join('{} -> {}'.format(k, v)
                                            for k, v in pkgs.items()))

    if check:
        missing = []
        installed = info_installed_packages()

        for name, version in pkgs:
            if name not in installed or not installed[name].eq_version(version):
                missing.append((name, version))
    else:
        missing = pkgs.keys()

    log.debug('Installing packages: {}'.format(missing))

    if not missing:
        return Unchanged('Packages {!r} already installed'.format(pkgs.keys()))

    # FIXME: see above
    info_installed_packages.invalidate_cache()

    with fs.remote_tmpdir() as rtmp:
        # upload packages to be installed
        pkg_files = []
        for idx, key in enumerate(missing):
            tmpdest = remote.path.join(rtmp, str(idx) + '.deb')
            fs.upload_file(pkgs[key], tmpdest)
            pkg_files.append(tmpdest)

        # install in a single dpkg install line
        # FIXME: add debconf default and such (same as apt)
        args = [config['cmd_dpkg'], '-i']
        args.extend(pkg_files)
        proc.run(
            args, extra_env={
                'DEBIAN_FRONTEND': 'noninteractive',
            })

    return Changed(msg='Installed packages {!r}'.format(missing))
示例#2
0
文件: apt.py 项目: mbr/remand
def dpkg_install(paths, check=True):
    pkgs = paths
    if not hasattr(paths, 'keys'):
        pkgs = {}

        # determine package names from filenames. ideally, we would open the
        # package here and check
        for p in paths:
            fn = os.path.basename(p)
            try:
                name, version, tail = fn.split('_', 3)
                pkgs[(name, version)] = p
            except ValueError:
                raise ValueError(
                    'Could not determine package version from '
                    'package filename {}. Please rename the .deb '
                    'to standard debian convention '
                    '(name_version_arch.deb) or supply a specific '
                    'version by passing a dictionary parameter.'.format(fn))

    # log names
    log.debug('Package names: ' + ', '.join('{} -> {}'.format(k, v)
                                            for k, v in pkgs.items()))

    if check:
        missing = []
        installed = info_installed_packages()

        for name, version in pkgs:
            if name not in installed or not installed[name].eq_version(
                    version):
                missing.append((name, version))
    else:
        missing = pkgs.keys()

    log.debug('Installing packages: {}'.format(missing))

    if not missing:
        return Unchanged('Packages {!r} already installed'.format(pkgs.keys()))

    # FIXME: see above
    info_installed_packages.invalidate_cache()

    with fs.remote_tmpdir() as rtmp:
        # upload packages to be installed
        pkg_files = []
        for idx, key in enumerate(missing):
            tmpdest = remote.path.join(rtmp, str(idx) + '.deb')
            fs.upload_file(pkgs[key], tmpdest)
            pkg_files.append(tmpdest)

        # install in a single dpkg install line
        # FIXME: add debconf default and such (same as apt)
        args = [config['cmd_dpkg'], '-i']
        args.extend(pkg_files)
        proc.run(args, extra_env={'DEBIAN_FRONTEND': 'noninteractive', })

    return Changed(msg='Installed packages {!r}'.format(missing))
示例#3
0
文件: ssl.py 项目: mbr/remand
def install_cert(cert, key, cert_name=None, key_name=None):
    cert_name = cert_name or os.path.basename(cert)
    key_name = key_name or os.path.basename(key)

    # small sanity check
    with open(cert) as f:
        if 'PRIVATE' in f.read():
            raise ValueError(
                'You seem to have passed a private key as a cert!')

    with open(key) as f:
        if 'PRIVATE' not in f.read():
            raise ValueError(
                '{} does not seem to be a valid private key'.format(key))

    # check if remote is reasonably secure
    cert_dir = config['sslcert_cert_dir']
    cert_dir_st = remote.lstat(cert_dir)

    if not cert_dir_st:
        raise ConfigurationError('Remote SSL dir {} does not exist'.format(
            cert_dir))

    key_dir = config['sslcert_key_dir']
    key_dir_st = remote.lstat(key_dir)

    if not key_dir_st:
        raise ConfigurationError('Remote key dir {} does not exist'.format(
            key_dir))

    SECURE_MODES = (0o700, 0o710)
    actual_mode = key_dir_st.st_mode & 0o777
    if actual_mode not in SECURE_MODES:
        raise ConfigurationError(
            'Mode of remote key dir {} is {:o}, should be one of {:o}'.format(
                key_dir, actual_mode, SECURE_MODES))

    if key_dir_st.st_uid != 0:
        raise ConfigurationError(
            'Remove key dir {} is not owned by root'.format(key_dir))

    # we can safely upload the key and cert
    cert_rpath = remote.path.join(cert_dir, cert_name)
    key_rpath = remote.path.join(key_dir, key_name)

    changed = False
    changed |= fs.upload_file(cert, cert_rpath).changed
    changed |= fs.upload_file(key, key_rpath).changed
    changed |= fs.chmod(key_rpath, 0o600).changed

    if changed:
        return Changed(
            msg='Uploaded key pair {}/{}'.format(cert_name, key_name))

    return Unchanged(
        msg='Key pair {}/{} already uploaded'.format(cert_name, key_name))
示例#4
0
文件: ssh.py 项目: mbr/remand
def install_private_key(key_file,
                        user='******',
                        key_type='rsa',
                        target_path=None):

    if target_path is None:
        # FIXME: auto-determine key type if None
        if key_type not in ('rsa', ):
            raise NotImplementedError('Key type {} not supported')

        fn = 'id_' + key_type
        target_path = remote.path.join(info['posix.users'][user].home, '.ssh',
                                       fn)

    changed = False

    # blocked: SSH transport does not suppoort
    # with remote.umasked(0o777 - KEY_FILE_PERMS):
    changed |= fs.create_dir(
        remote.path.dirname(target_path),
        mode=AK_DIR_PERMS).changed

    changed |= fs.upload_file(key_file, target_path).changed
    changed |= fs.chmod(target_path, mode=KEY_FILE_PERMS).changed

    if changed:
        return Changed(msg='Installed private key {}'.format(target_path))
    return Unchanged(
        msg='Private key {} already installed'.format(target_path))
示例#5
0
def install_private_key(key_file,
                        user='******',
                        key_type='rsa',
                        target_path=None):

    if target_path is None:
        # FIXME: auto-determine key type if None
        if key_type not in ('rsa', ):
            raise NotImplementedError('Key type {} not supported')

        fn = 'id_' + key_type
        target_path = remote.path.join(info['posix.users'][user].home, '.ssh',
                                       fn)

    changed = False

    # blocked: SSH transport does not suppoort
    # with remote.umasked(0o777 - KEY_FILE_PERMS):
    changed |= fs.create_dir(remote.path.dirname(target_path),
                             mode=AK_DIR_PERMS).changed

    changed |= fs.upload_file(key_file, target_path).changed
    changed |= fs.chmod(target_path, mode=KEY_FILE_PERMS).changed

    if changed:
        return Changed(msg='Installed private key {}'.format(target_path))
    return Unchanged(
        msg='Private key {} already installed'.format(target_path))
示例#6
0
def install_hostkeys(base_dir):
    results = []

    for key_type in ('ecdsa', 'ed25519', 'rsa'):
        fn = 'ssh_host_' + key_type + '_key'
        pub_fn = fn + '.pub'
        sk = os.path.join(base_dir, fn)
        pk = os.path.join(base_dir, pub_fn)

        results.append(fs.upload_file(sk, '/etc/ssh/' + fn))
        results.append(fs.upload_file(pk, '/etc/ssh/' + pub_fn))

    if util.any_changed(*results):
        systemd.reload_unit('ssh.service')
        return Changed(msg='Installed SSH hostkeys from {}'.format(base_dir))

    return Unchanged(msg='SSH hostkeys already installed')
示例#7
0
文件: __init__.py 项目: mbr/remand
def install_docker_compose():
    # docker: install docker compose
    ch = fs.upload_file(docker.webfiles["docker-compose-Linux-x86_64"], "/usr/local/bin/docker-compose").changed
    ch |= fs.chmod("/usr/local/bin/docker-compose", mode=0o755).changed

    if ch:
        return Changed(msg="Installed docker-compose")
    return Unchanged(msg="docker-compose already installed")
示例#8
0
def install_docker_compose():
    # docker: install docker compose
    ch = fs.upload_file(docker.webfiles['docker-compose-Linux-x86_64'],
                        '/usr/local/bin/docker-compose').changed
    ch |= fs.chmod('/usr/local/bin/docker-compose', mode=0o755).changed

    if ch:
        return Changed(msg='Installed docker-compose')
    return Unchanged(msg='docker-compose already installed')
示例#9
0
def install_source_list(path, name=None, main=False):
    if main:
        if name is not None:
            raise ValueError('Cannot provide name when uploading sources.list')

        op = fs.upload_file(
            path, config['apt_sources_list'], create_parent=True)

    else:
        op = fs.upload_file(
            path,
            remote.path.join(config['apt_sources_list_d'], name
                             or os.path.basename(path)),
            create_parent=True)

    if op.changed:
        info_update_timestamp().mark_stale()

    return op
示例#10
0
文件: apt.py 项目: mbr/remand
def install_source_list(path, name=None, main=False):
    if main:
        if name is not None:
            raise ValueError('Cannot provide name when uploading sources.list')

        op = fs.upload_file(path,
                            config['apt_sources_list'],
                            create_parent=True)

    else:
        op = fs.upload_file(path,
                            remote.path.join(config['apt_sources_list_d'],
                                             name or os.path.basename(path)),
                            create_parent=True)

    if op.changed:
        info_update_timestamp().mark_stale()

    return op
示例#11
0
文件: apt.py 项目: mbr/remand
def install_preference(path, name=None):
    op = fs.upload_file(path,
                        remote.path.join(config['apt_preferences_d'], name or
                                         os.path.basename(path)),
                        create_parent=True)

    if op.changed:
        info_update_timestamp().mark_stale()

    return op
示例#12
0
def install_preference(path, name=None):
    op = fs.upload_file(
        path,
        remote.path.join(config['apt_preferences_d'], name
                         or os.path.basename(path)),
        create_parent=True)

    if op.changed:
        info_update_timestamp().mark_stale()

    return op
示例#13
0
文件: systemd.py 项目: mbr/remand
def install_unit_file(unit_file, reload=True):
    base, ext = os.path.splitext(unit_file)

    if ext not in UNIT_EXTS:
        raise ValueError('unit_file should be one of {}'.format(UNIT_EXTS))

    remote_unit = os.path.join(config['systemd_unit_dir'],
                               os.path.basename(unit_file))

    if fs.upload_file(unit_file, remote_unit).changed:
        if reload:
            daemon_reload()
        return Changed(msg='Installed {}'.format(remote_unit))

    return Unchanged(msg='{} already installed'.format(remote_unit))
示例#14
0
文件: systemd.py 项目: mbr/remand
def install_unit_file(unit_file, reload=True):
    base, ext = os.path.splitext(unit_file)

    if ext not in UNIT_EXTS:
        raise ValueError('unit_file should be one of {}'.format(UNIT_EXTS))

    remote_unit = os.path.join(config['systemd_unit_dir'],
                               os.path.basename(unit_file))

    if fs.upload_file(unit_file, remote_unit).changed:
        if reload:
            daemon_reload()
        return Changed(msg='Installed {}'.format(remote_unit))

    return Unchanged(msg='{} already installed'.format(remote_unit))
示例#15
0
文件: systemd.py 项目: mbr/remand
def install_network_file(network_file, reload=True):
    base, ext = os.path.splitext(network_file)

    if ext not in NETWORK_EXTS:
        raise ValueError('network_file should be one of {}'.format(
            NETWORK_EXTS))

    remote_network = os.path.join(config['systemd_network_dir'],
                                  os.path.basename(network_file))

    if fs.upload_file(network_file, remote_network).changed:
        if reload:
            daemon_reload()
        return Changed(msg='Installed {}'.format(remote_network))

    return Unchanged(msg='{} already installed'.format(remote_network))
示例#16
0
文件: systemd.py 项目: mbr/remand
def install_network_file(network_file, reload=True):
    base, ext = os.path.splitext(network_file)

    if ext not in NETWORK_EXTS:
        raise ValueError(
            'network_file should be one of {}'.format(NETWORK_EXTS))

    remote_network = os.path.join(config['systemd_network_dir'],
                                  os.path.basename(network_file))

    if fs.upload_file(network_file, remote_network).changed:
        if reload:
            daemon_reload()
        return Changed(msg='Installed {}'.format(remote_network))

    return Unchanged(msg='{} already installed'.format(remote_network))
示例#17
0
文件: __init__.py 项目: mbr/remand
def setup_rsyslog(server_addr):
    # setup papertrail
    # FIXME: this is part of remand now
    changed = False
    changed = apt.install_packages(['rsyslog-gnutls']).changed
    changed |= fs.upload_file(papertrail.files['papertrail-bundle.pem'],
                              '/etc/papertrail-bundle.pem').changed
    changed |= fs.upload_string(
        papertrail.templates.render('papertrail.conf',
                                    addr=server_addr),
        '/etc/rsyslog.d/papertrail.conf', ).changed

    if changed:
        systemd.restart_unit('rsyslog.service')
        return Changed(
            msg='Setup papertrail logging to {}'.format(server_addr))
    return Unchanged(msg='Papertrail already setup to {}'.format(server_addr))
示例#18
0
文件: __init__.py 项目: mbr/remand
def setup_rsyslog(server_addr):
    # setup papertrail
    # FIXME: this is part of remand now
    changed = False
    changed = apt.install_packages(['rsyslog-gnutls']).changed
    changed |= fs.upload_file(papertrail.files['papertrail-bundle.pem'],
                              '/etc/papertrail-bundle.pem').changed
    changed |= fs.upload_string(
        papertrail.templates.render('papertrail.conf', addr=server_addr),
        '/etc/rsyslog.d/papertrail.conf',
    ).changed

    if changed:
        systemd.restart_unit('rsyslog.service')
        return Changed(
            msg='Setup papertrail logging to {}'.format(server_addr))
    return Unchanged(msg='Papertrail already setup to {}'.format(server_addr))
示例#19
0
def enable_letsencrypt(auto_reload=True, remove_default=True):
    changed = any_changed(
        fs.upload_file(nginx.files['acme-challenge'],
                       '/etc/nginx/sites-available/acme-challenge'),
        fs.symlink('/etc/nginx/sites-available/acme-challenge',
                   '/etc/nginx/sites-enabled/00_acme-challenge'),
    )

    fs.create_dir('/var/www/html/.well-known')
    fs.create_dir('/var/www/html/.well-known/acme-challenge')
    fs.chmod('/var/www/html/.well-known', mode=0o755)
    fs.chmod('/var/www/html/.well-known/acme-challenge', mode=0o755)

    if remove_default:
        changed |= fs.remove_file('/etc/nginx/sites-enabled/default').changed

    if changed:
        if auto_reload:
            systemd.reload_unit('nginx.service', only_if_running=True)

        return Changed(msg='Enabled nginx Let\'s encrypt support')
    return Unchanged(msg='nginx Let\'s encrypt support already enabled')
示例#20
0
文件: ssl.py 项目: mbr/remand
def install_cert(cert, key, cert_name=None, key_name=None):
    """Installs an SSL certificate with including key on the remote

    Certificate filenames are unchanged, per default they will be installed in
    `/etc/ssl`, with the corresponding keys at `/etc/ssl/private`."""
    cert_name = cert_name or os.path.basename(cert)
    key_name = key_name or os.path.basename(key)

    # small sanity check
    with open(cert) as f:
        if 'PRIVATE' in f.read():
            raise ValueError(
                'You seem to have passed a private key as a cert!')

    with open(key) as f:
        if 'PRIVATE' not in f.read():
            raise ValueError(
                '{} does not seem to be a valid private key'.format(key))

    # check if remote is reasonably secure
    cert_dir = config['sslcert_cert_dir']
    cert_dir_st = remote.lstat(cert_dir)

    if not cert_dir_st:
        raise ConfigurationError(
            'Remote SSL dir {} does not exist'.format(cert_dir))

    key_dir = config['sslcert_key_dir']
    key_dir_st = remote.lstat(key_dir)

    if not key_dir_st:
        raise ConfigurationError(
            'Remote key dir {} does not exist'.format(key_dir))

    SECURE_MODES = (0o700, 0o710)
    actual_mode = key_dir_st.st_mode & 0o777
    if actual_mode not in SECURE_MODES:
        raise ConfigurationError(
            'Mode of remote key dir {} is {:o}, should be one of {:o}'.format(
                key_dir, actual_mode, SECURE_MODES))

    if key_dir_st.st_uid != 0:
        raise ConfigurationError(
            'Remove key dir {} is not owned by root'.format(key_dir))

    # we can safely upload the key and cert
    cert_rpath = remote.path.join(cert_dir, cert_name)
    key_rpath = remote.path.join(key_dir, key_name)

    changed = False
    changed |= fs.upload_file(cert, cert_rpath).changed
    changed |= fs.upload_file(key, key_rpath).changed
    changed |= fs.chmod(key_rpath, 0o640).changed
    changed |= fs.chown(key_rpath, uid='root', gid='ssl-cert').changed

    if changed:
        return Changed(
            msg='Uploaded key pair {}/{}'.format(cert_name, key_name))

    return Unchanged(
        msg='Key pair {}/{} already uploaded'.format(cert_name, key_name))