def init_authorized_keys(user='******', fix_permissions=True): ak_file = get_authorized_keys_file(user) ak_dir = remote.path.dirname(ak_file) changed = False # ensure the directory exists changed |= fs.create_dir(ak_dir, mode=AK_DIR_PERMS).changed if fix_permissions: changed |= fs.chmod(ak_dir, AK_DIR_PERMS).changed changed |= fs.chown(ak_dir, uid=user).changed # check if the authorized keys file exists if not remote.lstat(ak_file): changed |= fs.touch(ak_file).changed if fix_permissions: changed |= fs.chmod(ak_file, AK_FILE_PERMS).changed changed |= fs.chown(ak_dir, uid=user).changed # at this point, we have fixed permissions for file and dir, as well as # ensured they exist. however, they might still be owned by root if changed: return Changed(ak_file, msg='Changed permissions or owner on authorized keys') return Unchanged( ak_file, msg='authorized keys file has correct owner and permissions')
def init_authorized_keys(user='******', fix_permissions=True): ak_file = get_authorized_keys_file(user) ak_dir = remote.path.dirname(ak_file) changed = False # ensure the directory exists changed |= fs.create_dir(ak_dir, mode=AK_DIR_PERMS).changed if fix_permissions: changed |= fs.chmod(ak_dir, AK_DIR_PERMS).changed # check if the authorized keys file exists if not remote.lstat(ak_file): changed |= fs.touch(ak_file).changed if fix_permissions: changed |= fs.chmod(ak_file, AK_FILE_PERMS).changed # at this point, we have fixed permissions for file and dir, as well as # ensured they exist. however, they might still be owned by root if changed: return Changed(ak_file, msg='Changed permissions or owner on authorized keys') return Unchanged( ak_file, msg='authorized keys file has correct owner and permissions')
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))
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))
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")
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')
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))
def set_authorized_keys(files, user='******', fix_permissions=True): ak_file = init_authorized_keys(user, fix_permissions).value kf = KeyFile() for fn in files: kf.add_from_file(fn) # directory is guaranteed to exist now, with correct permissions upload = fs.upload_string(str(kf), ak_file) if upload.changed and fix_permissions: fs.chmod(ak_file, AK_FILE_PERMS) fps = ', '.join(k.readable_fingerprint for k in kf.keys) if upload.changed: return Changed( msg='SSH authorized keys for {} set to: {}'.format(user, fps)) return Unchanged( msg='SSH authorized keys for {} unchanged ({})'.format(user, fps))
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')
def set_authorized_keys(files, user='******', fix_permissions=True): ak_file = init_authorized_keys(user, fix_permissions).value kf = KeyFile() for fn in files: kf.add_from_file(fn) # directory is guaranteed to exist now, with correct permissions upload = fs.upload_string(str(kf), ak_file) if upload.changed and fix_permissions: fs.chmod(ak_file, AK_FILE_PERMS) fs.chown(ak_file, uid=user) fps = ', '.join(k.readable_fingerprint for k in kf.keys) if upload.changed: return Changed( msg='SSH authorized keys for {} set to: {}'.format(user, fps)) return Unchanged( msg='SSH authorized keys for {} unchanged ({})'.format(user, fps))
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))