Esempio n. 1
0
def add_authorized_key(ssh_keys):
    remote_public_key = ssh_keys.get_remote('public-ssh-key')
    hookenv.log("Adding key: " + remote_public_key)
    ssh.add_authorized_key(remote_public_key,
                           utils.get_paths()['authorized-keys'])
    ssh_peer = {ssh_keys.get_remote('private-address'): remote_public_key}
    utils.update_config(config_path=utils.get_paths()['config'],
                        new_ssh_peers=ssh_peer)
    ssh_keys.remove_state(ssh_keys.states.new_remote_public_key)
Esempio n. 2
0
def configure_reprepro(mirrors, sign_key_fingerprint, sign_key_passphrase):
    """Create reprepro configuration files.

    The provided mirrors is a sequence of mirror.Mirror named tuples.
    """
    paths = get_paths()
    # Explicitly pass owner and group for tests, otherwise root would be used.
    owner = group = getpass.getuser()
    # Render distributions file.
    target = str(paths['reprepro-conf'] / 'distributions')
    context = {
        'mirrors': mirrors,
        'sign_script': paths['bin'] / 'reprepro-sign-helper',
    }
    render(_DISTRIBUTIONS, target, context, owner=owner, group=group)
    # Render updates file.
    target = str(paths['reprepro-conf'] / 'updates')
    context = {'mirrors': mirrors}
    render(_UPDATES, target, context, owner=owner, group=group)
    # Update configuration.
    update_config(config_path=paths['config'],
                  suites=[mirror.local_suite for mirror in mirrors],
                  sign_key_id=sign_key_fingerprint)
    # Save the sign passphrase for the signing helper script.
    with paths['sign-passphrase'].open('w') as fh:
        fh.write(sign_key_passphrase)
Esempio n. 3
0
 def test_disable_not_enabled(self):
     """Disabling mirror when not configured is a no-op."""
     paths = get_paths(root_dir=Path(self.fakes.fs.root.path))
     config = paths['config']
     disable_mirroring(get_paths=lambda: paths)
     self.assertFalse(config.exists())
     self.assertFalse(config.with_suffix('.disabled').exists())
 def test_configuration_files(self):
     """configure_reprepro writes rerepro config files."""
     paths = get_paths(root_dir=Path(self.fakes.fs.root.path))
     uri = 'https://*****:*****@example.com/ubuntu xenial main universe'
     configure_reprepro(uri,
                        'i386 amd64',
                        'ABABABAB',
                        'CDCDCDCD',
                        'very secret',
                        get_paths=lambda: paths)
     self.assertEqual(
         textwrap.dedent('''\
             Codename: xenial
             Label: xenial archive
             Components: main universe
             Architectures: i386 amd64
             SignWith: ! {}/reprepro-sign-helper
             Update: update-repo
             '''.format(paths['bin'])),
         (paths['reprepro-conf'] / 'distributions').read_text())
     self.assertEqual(
         textwrap.dedent('''\
             Name: update-repo
             Method: https://user:[email protected]/ubuntu
             Suite: xenial
             Components: main universe
             Architectures: i386 amd64
             VerifyRelease: ABABABAB
             '''), (paths['reprepro-conf'] / 'updates').read_text())
     self.assertEqual({
         'suite': 'xenial',
         'sign-key-id': 'CDCDCDCD'
     }, yaml.load(paths['config'].read_text()))
Esempio n. 5
0
def make_reprepro_files(root_dir, mirrors):
    """A tiny wrapper around configure_reprepro with testing paths."""
    paths = get_paths(root_dir=Path(root_dir))
    with mock.patch('charms.archive_auth_mirror.repository.get_paths',
                    return_value=paths):
        configure_reprepro(mirrors, sign_key_fingerprint, sign_key_passphrase)
    return paths
Esempio n. 6
0
def configure_reprepro(mirror_uri,
                       mirror_archs,
                       mirror_key_fingerprint,
                       sign_key_fingerprint,
                       sign_key_passphrase,
                       get_paths=get_paths):
    """Create reprepro configuration files."""
    paths = get_paths()
    context = split_repository_uri(mirror_uri)
    context.update({
        'archs': mirror_archs,
        'mirror_key': mirror_key_fingerprint,
        'sign_key': sign_key_fingerprint,
        'sign_script': paths['bin'] / 'reprepro-sign-helper'
    })

    # explicitly pass owner and group for tests, otherwise root would be used
    owner = group = getpass.getuser()
    render('reprepro-distributions.j2',
           str(paths['reprepro-conf'] / 'distributions'),
           context,
           owner=owner,
           group=group)
    render('reprepro-updates.j2',
           str(paths['reprepro-conf'] / 'updates'),
           context,
           owner=owner,
           group=group)
    update_config(config_path=paths['config'],
                  suite=context['suite'],
                  sign_key_id=context['sign_key'])
    # save the sign passphrase for the signing helper script
    with paths['sign-passphrase'].open('w') as fh:
        fh.write(sign_key_passphrase)
Esempio n. 7
0
 def test_disable_twice(self):
     """disable_mirroring can be called multiple times."""
     paths = get_paths(root_dir=Path(self.fakes.fs.root.path))
     config = paths['config']
     disable_mirroring(get_paths=lambda: paths)
     disable_mirroring(get_paths=lambda: paths)
     self.assertFalse(config.exists())
     self.assertFalse(config.with_suffix('.disabled').exists())
Esempio n. 8
0
def get_virtualhost_config(hookenv=hookenv):
    """Return the configuration for the static virtuahost."""
    paths = get_paths()
    domain = get_virtualhost_name(hookenv=hookenv)
    return {
        'domain': domain,
        'document_root': str(paths['static']),
        'basic_auth_file': str(paths['basic-auth'])}
Esempio n. 9
0
def get_virtualhost_config(auth_backends=None, auth_cache_time=None,
                           hookenv=hookenv):
    """Return the configuration for the static virtuahost."""
    paths = get_paths()
    domain = get_virtualhost_name(hookenv=hookenv)
    return {
        'domain': domain,
        'document_root': str(paths['static']),
        'auth_backends': auth_backends or [],
        'auth_cache_time': auth_cache_time,
        'basic_auth_file': str(paths['basic-auth'])}
Esempio n. 10
0
    def test_install_crontab(self):
        """install_crontab creates a crontab file"""
        root_dir = Path(self.fakes.fs.root.path)
        (root_dir / 'etc/cron.d').mkdir(parents=True)
        paths = get_paths(root_dir=root_dir)
        install_crontab(paths=paths)

        with paths['cron'].open() as fh:
            content = fh.read()

        script = paths['bin'] / 'mirror-archive'
        self.assertIn(str(script), content)
Esempio n. 11
0
    def test_detach_sign(self):
        """detach_sign creates a detached signature for a file."""
        paths = get_paths(root_dir=Path(self.fakes.fs.root.path))
        paths['gnupghome'].mkdir(parents=True)
        paths['sign-passphrase'].write_text('')
        keyring = make_keyring(paths['gnupghome'])
        fingerprint = keyring.import_key(SECRET_KEY_MATERIAL)

        unsigned_file = Path(self.fakes.fs.root.join('unsigned'))
        unsigned_file.write_text('some text to sign')
        detach_sign_file = Path(self.fakes.fs.root.join('signature'))

        detach_sign(fingerprint, unsigned_file, detach_sign_file, paths=paths)

        signature = detach_sign_file.read_text()
        self.assertTrue(signature.startswith('-----BEGIN PGP SIGNATURE-----'))
        self.assertTrue(signature.endswith('-----END PGP SIGNATURE-----\n'))
Esempio n. 12
0
    def test_inline_sign(self):
        """inline_sign creates an inline signature for a file."""
        paths = get_paths(root_dir=Path(self.fakes.fs.root.path))
        paths['gnupghome'].mkdir(parents=True)
        paths['sign-passphrase'].write_text('')
        keyring = make_keyring(paths['gnupghome'])
        fingerprint = keyring.import_key(SECRET_KEY_MATERIAL)

        unsigned_file = Path(self.fakes.fs.root.join('unsigned'))
        unsigned_file.write_text('some text to sign')
        inline_sign_file = Path(self.fakes.fs.root.join('signed'))

        inline_sign(fingerprint, unsigned_file, inline_sign_file, paths=paths)

        signed_content = inline_sign_file.read_text()
        self.assertIn('some text to sign', signed_content)
        self.assertIn('-----BEGIN PGP SIGNATURE-----', signed_content)
Esempio n. 13
0
def get_virtualhost_config(auth_backends,
                           resource_name,
                           auth_cache_enabled,
                           auth_cache_duration,
                           auth_cache_inactivity,
                           hookenv=hookenv):
    """Return the configuration for the static virtuahost."""
    paths = get_paths()
    domain = get_virtualhost_name(hookenv=hookenv)
    return {
        'domain': domain,
        'document_root': str(paths['static']),
        'auth_backends': auth_backends or [],
        'resource_name': resource_name,
        'auth_cache_enabled': auth_cache_enabled,
        'auth_cache_duration': auth_cache_duration,
        'auth_cache_inactivity': auth_cache_inactivity,
        'basic_auth_file': str(paths['basic-auth'])
    }
    def test_disable_mirroring(self):
        """disable_mirroring renames the script config file."""
        paths = get_paths(root_dir=Path(self.fakes.fs.root.path))
        uri = 'https://*****:*****@example.com/ubuntu xenial main universe'
        configure_reprepro(uri,
                           'i386 amd64',
                           'ABABABAB',
                           'CDCDCDCD',
                           'very secret',
                           get_paths=lambda: paths)

        config = paths['config']
        self.assertTrue(config.exists())
        orig_content = config.read_text()
        disable_mirroring(get_paths=lambda: paths)
        self.assertFalse(config.exists())
        # The file is moved to .disabled
        disabled_file = config.with_suffix('.disabled')
        self.assertTrue(disabled_file.exists())
        self.assertEqual(orig_content, disabled_file.read_text())
Esempio n. 15
0
def install_resources(root_dir=None):
    """Create tree structure and install resources from the charm."""
    paths = get_paths(root_dir=root_dir)
    for name in ('bin', 'reprepro-conf', 'static'):
        host.mkdir(str(paths[name]), perms=0o755)

    # the gpg directory should only be readable by root
    host.mkdir(str(paths['gnupghome']), perms=0o700)

    # create an empty basic-auth password file. It will be updated by a script
    # run as root, but it must be readable by the web server
    host.write_file(
        str(paths['basic-auth']), b'', group='www-data', perms=0o640)
    # create an empty sign passphrase file, only readable by root
    host.write_file(str(paths['sign-passphrase']), b'', perms=0o600)

    # install scripts
    for script in SCRIPTS:
        create_script_file(script, paths['bin'])
    # symlink the lib libary to make it available to scripts too
    (paths['bin'] / 'lib').symlink_to(Path.cwd() / 'lib')
Esempio n. 16
0
 def test_get_paths(self):
     """get_paths returns service paths."""
     paths = get_paths()
     self.assertEqual(
         {
             'base': Path('/srv/archive-auth-mirror'),
             'cron': Path('/etc/cron.d/archive-auth-mirror'),
             'bin': Path('/srv/archive-auth-mirror/bin'),
             'config': Path('/srv/archive-auth-mirror/config.yaml'),
             'static': Path('/srv/archive-auth-mirror/static'),
             'basic-auth': Path('/srv/archive-auth-mirror/basic-auth'),
             'sign-passphrase':
             Path('/srv/archive-auth-mirror/sign-passphrase'),
             'ssh-key': Path('/srv/archive-auth-mirror/ssh-key'),
             'authorized-keys': Path('/root/.ssh/authorized_keys'),
             'lockfile':
             Path('/srv/archive-auth-mirror/mirror-archive.lock'),
             'reprepro': Path('/srv/archive-auth-mirror/reprepro'),
             'reprepro-conf':
             Path('/srv/archive-auth-mirror/reprepro/conf'),
             'gnupghome': Path('/srv/archive-auth-mirror/reprepro/.gnupg')
         }, paths)
def config_set():
    config = hookenv.config()
    missing_options = setup.missing_options(config)
    if missing_options:
        hookenv.status_set(
            'blocked',
            'Mirroring is disabled as some configuration options are missing: '
            '{}'.format(', '.join(missing_options)))
        return

    # Configure mirroring.
    keyring = gpg.KeyRing()
    mirrors = mirror.from_config(keyring, config['mirrors'],
                                 config['repository-origin'].strip())
    sign_key_fingerprint = keyring.import_key(config['sign-gpg-key'])
    sign_key_passphrase = config.get('sign-gpg-passphrase', '').strip()
    repository.configure_reprepro(mirrors, sign_key_fingerprint,
                                  sign_key_passphrase)
    # Export the public key used to sign the repository.
    _export_sign_key(sign_key_fingerprint)
    hookenv.status_set('active', 'Mirroring configured')
    # Update scripts config.
    utils.update_config(config_path=utils.get_paths()['config'],
                        packages_require_auth=config['packages-require-auth'])
Esempio n. 18
0
def set_ssh_key(ssh_keys):
    public_key_path = str(utils.get_paths()['ssh-key']) + '.pub'
    with open(public_key_path, 'r') as public_key_file:
        public_key = public_key_file.read()
    ssh_keys.set_local_public_key(public_key)
Esempio n. 19
0
 def setUp(self):
     super().setUp()
     root_dir = Path(self.fakes.fs.root.path)
     (root_dir / 'etc/cron.d').mkdir(parents=True)
     self.paths = get_paths(root_dir=root_dir)
Esempio n. 20
0
def create_ssh_key():
    ssh.create_key(utils.get_paths()['ssh-key'])
Esempio n. 21
0
def disable_mirroring(get_paths=get_paths):
    """Disable mirroring."""
    config = get_paths()['config']
    if config.exists():
        config.replace(config.with_suffix('.disabled'))
Esempio n. 22
0
def _export_sign_key(key_id):
    """Export the public key for the repo under the static serve."""
    filename = utils.get_paths()['static'] / 'key.asc'
    gpg.export_public_key(key_id, filename)
Esempio n. 23
0
def create_ssh_key():
    path = utils.get_paths()['ssh-key']
    if not path.exists():
        # only_once doesn't protect the handler from running if the line in
        # source code changes (so it can run again in an upgrade-charm hook)
        ssh.create_key(path)