Add a key to the authorized_keys file, using a file as the source.

    CLI Example:

    .. code-block:: bash

        salt '*' ssh.set_auth_key_from_file <user> salt://ssh_keys/<user>.id_rsa.pub

def set_auth_key_from_file(user,
                           source,
                           config='.ssh/authorized_keys',
                           saltenv='base',
                           fingerprint_hash_type=None):
    '''
    Add a key to the authorized_keys file, using a file as the source.

    CLI Example:

    .. code-block:: bash

        salt '*' ssh.set_auth_key_from_file <user> salt://ssh_keys/<user>.id_rsa.pub
    '''
    # TODO: add support for pulling keys from other file sources as well
    lfile = __salt__['cp.cache_file'](source, saltenv)
    if not os.path.isfile(lfile):
        raise CommandExecutionError(
            'Failed to pull key file from salt file server'
        )

    s_keys = _validate_keys(lfile, fingerprint_hash_type)
    if not s_keys:
        err = (
            'No keys detected in {0}. Is file properly formatted?'.format(
                source
            )
        )
        log.error(err)
        __context__['ssh_auth.error'] = err
        return 'fail'
    else:
        rval = ''
        for key in s_keys:
            rval += set_auth_key(
                user,
                key,
                enc=s_keys[key]['enc'],
                comment=s_keys[key]['comment'],
                options=s_keys[key]['options'],
                config=config,
                cache_keys=list(s_keys.keys()),
                fingerprint_hash_type=fingerprint_hash_type
            )
        # Due to the ability for a single file to have multiple keys, it's
        # possible for a single call to this function to have both "replace"
        # and "new" as possible valid returns. I ordered the following as I
        # thought best.
        if 'fail' in rval:
            return 'fail'
        elif 'replace' in rval:
            return 'replace'
        elif 'new' in rval:
            return 'new'
        else:
            return 'no change'