geofront.remote — Remote sets

Every remote set is represented as a mapping (which is immutable, or mutable) of alias str to Remote object e.g.:

{
    'web-1': Remote('ubuntu', '192.168.0.5'),
    'web-2': Remote('ubuntu', '192.168.0.6'),
    'web-3': Remote('ubuntu', '192.168.0.7'),
    'worker-1': Remote('ubuntu', '192.168.0.25'),
    'worker-2': Remote('ubuntu', '192.168.0.26'),
    'db-1': Remote('ubuntu', '192.168.0.50'),
    'db-2': Remote('ubuntu', '192.168.0.51')
}

However, in the age of the cloud, you don’t have to manage the remote set since the most of cloud providers offer their API to list provisioned remote nodes.

Geofront provides builtin CloudRemoteSet, a subtype of collections.abc.Mapping, that proxies to the list dynamically made by cloud providers.

Changed in version 0.2.0: CloudRemoteSet is moved from this module to geofront.backends.cloud. See CloudRemoteSet.

class geofront.remote.AuthorizedKeyList(sftp_client: paramiko.sftp_client.SFTPClient)

List-like abstraction for remote authorized_keys.

Note that the contents are all lazily evaluated, so in order to pretend heavy duplicate communications over SFTP use list() to eagerly evaluate e.g.:

lazy_list = AuthorizedKeyList(sftp_client)
eager_list = list(lazy_list)
# ... some modifications on eager_list ...
lazy_list[:] = eager_list
Parameters:sftp_client (paramiko.sftp_client.SFTPClient) – the remote sftp connection to access authorized_keys
FILE_PATH = '.ssh/authorized_keys'

(str) The path of authorized_keys file.

class geofront.remote.DefaultPermissionPolicy

All remotes are listed and allowed for everyone in the team.

New in version 0.2.0.

class geofront.remote.GroupMetadataPermissionPolicy(metadata_key: str, separator: str=None)

Allow/disallow remotes according their metadata. It assumes every remote has a metadata key that stores a set of groups to allow. For example, suppose there’s the following remote set:

{
    'web-1': Remote('ubuntu', '192.168.0.5', metadata={'role': 'web'}),
    'web-2': Remote('ubuntu', '192.168.0.6', metadata={'role': 'web'}),
    'web-3': Remote('ubuntu', '192.168.0.7', metadata={'role': 'web'}),
    'worker-1': Remote('ubuntu', '192.168.0.25',
                       metadata={'role': 'worker'}),
    'worker-2': Remote('ubuntu', '192.168.0.26',
                       metadata={'role': 'worker'}),
    'db-1': Remote('ubuntu', '192.168.0.50', metadata={'role': 'db'}),
    'db-2': Remote('ubuntu', '192.168.0.51', metadata={'role': 'db'})
}

and there are groups identified as 'web', 'worker', and 'db'. So the following policy would allow only members who belong to the corresponding groups:

GroupMetadataPermissionPolicy(‘role’)
Parameters:
  • metadata_key (str) – the key to find corresponding groups in metadata of each remote
  • separator (str) – the character separates multiple group identifiers in the metadata value. for example, if the groups are stored as like 'sysadmin,owners' then it should be ','. it splits group identifiers by all whitespace characters by default

New in version 0.2.0.

class geofront.remote.PermissionPolicy

Permission policy determines which remotes are visible by a team member, and which remotes are allowed to SSH. So each remote can have one of three states for each team member:

Listed and allowed
A member can SSH to the remote.
Listed but disallowed
A member can be aware of the remote, but cannot SSH to it.
Unlisted and disallowed
A member can’t be aware of the remote, and can’t SSH to it either.
Unlisted but allowed
It is possible in theory, but mostly meaningless in practice.

The implementation of this interface has to implement two methods. One is filter() which determines whether remotes are listed or unlisted. Other one is permit() which determines whether remotes are allowed or disallowed to SSH.

New in version 0.2.0.

filter(remotes: collections.abc.Mapping, identity: geofront.identity.Identity, groups: collections.abc.Set) → collections.abc.Mapping

Determine which ones in the given remotes are visible to the identity (which belongs to groups). The resulted mapping of filtered remotes has to be a subset of the input remotes.

Parameters:
permit(remote: geofront.remote.Remote, identity: geofront.identity.Identity, groups: collections.abc.Set) → bool

Determine whether to allow the given identity (which belongs to groups) to SSH the given remote.

Parameters:
class geofront.remote.Remote(user: str, host: str, port: numbers.Integral=22, metadata: collections.abc.Mapping={})

Remote node to SSH.

Parameters:
  • user (str) – the username to ssh
  • host (str) – the host to access
  • port (numbers.Integral) – the port number to ssh. the default is 22 which is the default ssh port
  • metadata (collections.abc.Mapping) – optional metadata mapping. keys and values have to be all strings. empty by default

New in version 0.2.0: Added optional metadata parameter.

host = None

(Address) The hostname to access.

metadata = None

(collections.abc.Mapping) The additional metadata. Note that it won’t affect to hash() of the object, nor ==/= comparison of the object.

New in version 0.2.0.

port = None

(numbers.Integral) The port number to SSH.

user = None

(str) The username to SSH.

geofront.remote.authorize(public_keys: collections.abc.Set, master_key: paramiko.pkey.PKey, remote: geofront.remote.Remote, timeout: datetime.timedelta) → datetime.datetime

Make an one-time authorization to the remote, and then revokes it when timeout reaches soon.

Parameters:
Returns:

the expiration time

Return type:

datetime.datetime