Example #1
0
    def call_read_write_update_option(self, name, auth, jump_server=None,
                                      **kwargs):
        """Update secrets for an existing named authority.

        Args:
            name (str): The name of the authority to lookup.
            auth (str): Authentification method.

        Raises:
            Exception: If named authority does not exists.

        Outputs:
            stdout: Confirm message with human-readable authority details.
        """

        Log.debug("Incoming update request for named authority {n}", n=name)
        if not self.get_db().exists(name):
            Log.debug("Named authority is not found...")
            error = "Cannot update entry: \"{name}\" not found in " \
                    "keychain (missing key)"
            Log.fatal(error, name=name)
        if jump_server is not None:
            Log.debug("Update requests to change jump server...")
            jump_auth = self.build_authority_from_signature(jump_server)
            self.get_db().update_jump_auth(name, jump_auth)
            Log.debug("New jump set to authority: {a}", a=str(jump_auth))
        passkey = Passkey.resolve(auth)
        self.get_db().update_passkey(name, passkey)
        Log.debug("New passkey set ... ")
        Display.show_update(self.get_db().fetch_auth(name))
Example #2
0
    def read_tmp_secrets(self, zf_secrets):
        """Read temporary secrets.

        Args:
            zf_secrets (ZipFile): ZipFile instance with secrets and passkeys.

        Raises:
            SystemExit: If manager crashes or corrupted data are found.
        """

        for each in zf_secrets.read(self.migrate_tmpfile).split("\n"):
            line = each.split("\t", self.COLUMNS)
            if len(line) == 0:
                continue
            _, _, host, ipv4, port, user, scheme, name, ptype, passkey = line
            if ptype not in Passkey.SUPPORTED_TYPES:
                Log.fatal("Unsupported passkey storage {x}", x=ptype)
            authority_args = user, host, port, scheme
            auth = self.manager.build_authority_from_args(*authority_args)
            if ptype == "privatekey":
                passkey = zf_secrets.read(passkey)
            data = {
                "name": name,
                "host": host,
                "auth": auth,
                "passkey": Passkey.SUPPORTED_TYPES.get(ptype) + passkey
            }
            self.manager.get_db().add(**data)
        Log.warn("Unsupported import for jump server, yet")
Example #3
0
    def new(cls, host, port, user, scheme=None):
        """Create new authority instance.

        Args:
            host   (str): Hostname or IP address as an integer.
            port   (int): Port number of hostname.
            user   (str): Username assigned to hostname.
            scheme (str): Connection service scheme (optional).

        Raises:
            Exception: If required fields are invalid.

        Returns:
            Authority: An authority instance.
        """

        auth = cls()
        try:
            if scheme is not None:
                auth.set_scheme(scheme)
            auth.set_host(host)
            auth.set_port(port)
            auth.set_user(user)
        except Exception as e:
            Log.fatal("Cannot create new authority: {e}", e=str(e))
        return auth
Example #4
0
    def call_read_only_list_option(self, *args, **kwargs):
        """List handler.

        Outputs:
            stdout: Pager with table-like view of all hostnames.
        """

        Log.debug("Incoming list request...")
        known_hosts = [e for e in self.get_db().query_all()]
        counter = -1
        indexes = {}
        sorted_hosts = []
        Log.debug("Found {n} hosts to list...", n=len(known_hosts))
        while len(known_hosts) > 0:
            if counter >= self.MAX_ITER_LIST:
                Log.fatal("Max. iteration over list display reached...")
            name, auth, host, jump = known_hosts[0]
            counter += 1
            if auth.signature() not in indexes:
                indexes.update({auth.signature(): counter})
            if jump is None:
                sorted_hosts.append(known_hosts.pop(0))
                continue
            jump_index = indexes.get(jump.signature(), -1)
            if jump_index > -1:
                if jump_index == 0:
                    jump_index += 1
                sorted_hosts.insert(jump_index, known_hosts.pop(0))
                continue
            known_hosts.insert(len(known_hosts), known_hosts.pop(0))
        Log.debug("Sorted all known hosts and now preparing to print out...")
        Display.show_list_view(sorted_hosts, **self.args)
Example #5
0
    def get_scheme(self):
        """Authority scheme getter.

        Returns:
            unicode: Connection scheme.
        """

        if self.scheme is None:
            Log.fatal("Authority has not set a valid scheme: unset scheme")
        return unicode(self.scheme)
Example #6
0
    def get_user(self):
        """Authority user getter.

        Returns:
            unicode: Connection username.
        """

        if self.user is None:
            Log.fatal("Authority has not set a valid user: unset user")
        return unicode(self.user)
Example #7
0
    def read(self):
        """Autodetect read method and retrieve passkey.

        Raises:
            Exception: If cannot autodetect read method.
        """

        if not hasattr(self, self.__read_method):
            Log.fatal("Unsupported read method: {m}", m=self.read_method)
        self.passkey = getattr(self, self.__read_method)()
Example #8
0
def get_init_shell(self):
    """Shell getter for "init" option.
    """

    try:
        Secret.get_secret_file()
        print(OKAY_MESSAGE)
    except Exception as e:
        Log.fatal("Aborting due to an error: {e}", e=str(e))
    raise SystemExit
Example #9
0
    def get_secrets(self):
        """Keychain getter.

        Returns:
            Keychain: Passkeys storage.
        """

        if isinstance(self.__secrets, Keychain):
            return self.__secrets
        Log.fatal("Missing keychain: manager not initialized?")
Example #10
0
    def get_db(self):
        """Database getter.

        Returns:
            Database: Database storage.
        """

        if isinstance(self.__database, Database):
            return self.__database
        Log.fatal("Missing database: manager not initialized?")
Example #11
0
def get_install_shell(self):
    """Shell getter for "install" option.
    """

    try:
        deploy_unlock_script() and deploy_lock_script()
        print(SCRIPTS_CREATED)
    except Exception as e:
        Log.fatal("Aborting due to an error: {e}", e=str(e))
    raise SystemExit
Example #12
0
    def add(self, key, value):
        """Append key to keychain.

        Args:
            key   (str): Key to append.
            value (str): Value to save for given key.
        """

        if self.has(key):
            Log.fatal("Cannot add duplicates in keychain")
        self.update(key, value)
Example #13
0
    def pin(self):
        """Return the prefixed secret with its appropriate type.

        Raises:
            Exception: If unsupported passkey is provided.

        Returns:
            str: Prefixed passkey.
        """

        if self.passkey is None:
            Log.fatal("Passkey has not been read yet")
        return self.passfix + self.passkey
Example #14
0
    def sign(cls, data):
        """Calculate CRC32 hash of given data.

        Args:
            data (str): String data to calculate CRC.

        Returns:
            str: Hex value without 0x of the calculated CRC32.
        """

        if not isinstance(data, (str, unicode)):
            Log.fatal("Cannot calculate CRC for non-string data")
        return hex(crc32(data) & 0xFFFFFFFF)[2:]  # skip 0x
Example #15
0
    def add_host(self, name, host):
        """Create new hostname for named authority.

        Args:
            name (str): Full name of the authority to add.
            host (str): Hostname to save to keychain.

        Raises:
            Exception: If named authority already exists in keychain.
        """

        if self.storage.has(self.get_host_key(name)):
            Log.fatal("Cannot add hostname on a duplicate entry")
        self.storage.add(self.get_host_key(name), host)
Example #16
0
    def add_passkey(self, name, passkey):
        """Create new passkey for a named authority.

        Args:
            name    (str): Full name of the authority to add.
            passkey (str): Processed passkey to save to keychain.

        Raises:
            Exception: If named authority already exists in keychain.
        """

        if self.exists(name):
            Log.fatal("Cannot add passkey on a duplicate entry")
        self.update_passkey(name, passkey)
Example #17
0
    def update_jump_auth(self, name, auth):
        """Update passkey for existing named authority.

        Args:
            name       (str): Full name of the authority to add.
            auth (Authority): New authority as jump server.

        Raises:
            Exception: If provided argument is not Authority.
        """

        if not isinstance(auth, Authority):
            Log.fatal("Expected authority instance, got {t}", t=type(auth))
        self.storage.update(self.get_jump_key(name), auth.read())
Example #18
0
    def update_passkey(self, name, passkey):
        """Update passkey for existing named authority.

        Args:
            name    (str): Full name of the authority to add.
            passkey (str): New processed passkey to replace the old passkey.

        Raises:
            Exception: If passkey is zero-length.
        """

        if len(passkey) == 0:
            Log.fatal("Passkey cannot be empty")
        self.storage.update(self.get_pass_key(name), passkey)
Example #19
0
    def migrate_secrets(cls):
        """Migrate stored secrets from another version to current version.

        Raises:
            Exception: If secrets cannot be migrated.
        """

        fullpath = "{}/{}".format(cls.get_secret_dir(), cls.SECRETS_FILE)
        try:
            secret_file = read_secrets(fullpath, "c")
            secret_file[cls.VERSION] = __version__
            secret_file.close()
        except Exception as e:
            Log.fatal("Cannot migrate secrets because {e}", e=str(e))
Example #20
0
    def get_secret_file(cls):
        """Return or make a sample keys holder.

        Raises:
            Exception: If application cannot read or write file.

        Returns:
            object: Instance of opened secrets file.
        """

        secret_dir = cls.get_secret_dir()
        lockpath = "{}/{}".format(secret_dir, cls.SECRETS_LOCK)
        if path.exists(lockpath):
            Log.fatal("Secrets are locked!\nClosing...")
        fullpath = "{}/{}".format(secret_dir, cls.SECRETS_FILE)
        try:
            secret_file = read_secrets(fullpath, "c")
            chmod(fullpath, 0600)
        except Exception as e:
            Log.fatal("Cannot create secret storage file: {e}", e=str(e))
        try:
            assert secret_file[cls.VERSION]
        except KeyError:
            secret_file[cls.VERSION] = __version__
        except Exception as e:
            Log.fatal("Unsupported secrets driver or {e}", e=str(e))
        if secret_file[cls.VERSION] != __version__:
            error = "Secrets have been stored with a different version " \
                    "of Unlocker (current version {cv}; secrets {vs})\n" \
                    "Closing..."
            Log.fatal(error, cv=__version__, vs=secret_file[cls.VERSION])
        return secret_file
Example #21
0
    def add_auth(self, name, auth):
        """Create new authority for self named authority.

        Args:
            name       (str): Full name of the authority to add.
            auth (Authority): Authority instance to save to keychain.

        Raises:
            Exception: If named authority already exists in keychain.
        """

        if self.storage.has(self.get_auth_key(name)):
            Log.fatal("Cannot add authority on a duplicate entry")
        if not isinstance(auth, Authority):
            Log.fatal("Expected auth to be authority, got {t}", t=type(auth))
        self.storage.add(self.get_auth_key(name), auth.read())
Example #22
0
    def set_scheme(self, scheme):
        """Authority scheme setter.

        Args:
            scheme (str): Connection service scheme.

        Raises:
            Exception: if an invalid scheme is provided.
        """

        if not isinstance(scheme, (str, unicode)):
            Log.fatal("Invalid scheme: expected string, got {x}",
                      x=type(scheme))
        if len(scheme) == 0:
            Log.fatal("Invalid scheme: zero-length string not allowed")
        self.scheme = scheme
Example #23
0
    def shift(self, string):
        """Shift to the right a sting to remove any prefix.

        Args:
            string (str): String to be shifted.

        Raises:
            Exeption: If provided argument is not a string.

        Returns:
            str: New shifted string without prefix.
        """

        if isinstance(string, (str, unicode)):
            return string[self.PREFIX_FIXED_LEN:]
        Log.fatal("Unsupported shift operation on {t}", t=type(string))
Example #24
0
    def query(self, key_type_prefix):
        """Query secrets from keychain storage.

        Args:
            key_type_prefix (str): Prefix to partial match in lookup.

        Yields:
            mixt: Entry for each matched found.
        """

        for each in self.storage.lookup(key_type_prefix):
            if each == self.VERSION:
                continue
            if self.storage.get_value(each).strip() == "":
                Log.fatal("Storage contains empty value for key {k}", k=each)
            yield each
Example #25
0
    def get_prefix(self, prefix):
        """Prefix getter. Appends a separator and returns prefix.

        Args:
            prefix (str): The prefix to return.

        Raises:
            Exception: If size of prefix exceeds.

        Returns:
            str: New string of prefix with separator.
        """

        key = prefix + self.SEPARATOR
        if len(key) != self.PREFIX_FIXED_LEN:
            Log.fatal("Invalid prefixed key length, got {v}", v=len(key))
        return key
Example #26
0
    def set_port(self, port):
        """Authority port setter.

        Args:
            port (int): Port number of connection.

        Raises:
            Exception: if an invalid port is provided.
        """

        if isinstance(port, (str, unicode)):
            port = int(port)
        if not isinstance(port, int):
            Log.fatal("Invalid port: expected integer, got {x}", x=type(port))
        if port < self.MIN_PORT or port > self.MAX_PORT:
            Log.fatal("Invalid port: out of range {port}", port=port)
        self.port = port
Example #27
0
    def build_authority_from_signature(self, signature):
        """Generate authority from a signature.

        Args:
            signature (str): The signature to generate the authority.

        Raises:
            Exception: If no authority matches the signature provided.

        Returns:
            Authority: The authority with the signature provided.
        """

        for each, _ in self.get_db().query_auth():
            if each.signature() == signature:
                return each
        Log.fatal("Cannot find authority for signature {s}", s=signature)
Example #28
0
    def get_value(self, key):
        """Returns real value for given key.

        Args:
            key (str): Key to lookup and retrieve value.

        Raises:
            Exception: If value is None or keychain does not have key.

        Returns:
            str: Uncompressed and decoded stored value for key.
        """

        value = self.get(key)
        if value is None:
            Log.fatal("Keychain does not have requested key")
        return decompress(b64decode(value))
Example #29
0
    def find_port(cls, service):
        """Find port number for service.

        Args:
            service (str): Service scheme name.

        Raises:
            Exception: If service is not supported.

        Return:
            int: Port number for service.
        """

        for srv, port in cls.services:
            if srv == service:
                return port
        Log.fatal("Unsupported service {s}", s=service)
Example #30
0
    def lookup(self, lookup_name):
        """Lookup a named authority and return self, hostname and secret.

        Args:
            lookup_name (str): The name of the authority to find.

        Raises:
            Exception: If authority is not found.

        Returns:
            tuple: Authority instance, hostname and secret passkey.
        """

        for name, auth, host, jump in self.query_all():
            if name == lookup_name:
                secret = self.storage.get_value(self.get_pass_key(name))
                return auth, host, secret
        Log.fatal("Nothing found for name {n}", n=lookup_name)