Coder Social home page Coder Social logo

ssh_config's Issues

Allow non-interactive ssh-add

I want to put this as bash aliases, but I don't see any option to omit interactive question.

$ ssh-config add "cvps" HostName=192.168.140.1 Port=22 User=chris IdentityFile=""
Host cvps
    HostName 192.168.140.1
    User chris
    Port 22

Information is correct ? [y/N]: y
Added!
$

You should add --yes so one don't have to manually press y. Thanks ! Great program overall

Support multiple host patterns

SSH_CONFIG supports defining multiple host patterns:

Host  pattern1 pattern2
    IdentityFile file

But parsing this at the moment fails with an issue in pyparsing.

Unindented block and global options

Hello @haginara

Thanks for this useful lib.
I just found out that ssh_config does not support global options at the beginning of the file and unindented block ( indenting a block is always a good practice, but it's not required in the ssh config file ).

Here a dummy example of config file which leads to a WrongSSHConfig :

CanonicalizeHostname no
CanonicalDomains no

Host github.com
    User git
    IdentityFile ~/.ssh/id_github

or simply

Host github.com
User git
IdentityFile ~/.ssh/id_github

But both files have a "good" syntax.

I tried to modify the pattern defined with pyparsing in order to parse the unindented global options, but it only works partially :

    def parse(self, data=""):
        """Parse ssh-config data

        args:
            data (str)

        returns:
            Parsed config or None (dict)
        """

        if data:
            self.raw = data

        SPACE = White().suppress()
        SEP = Suppress(SPACE) | Suppress("=")
        HOST = CaselessLiteral("Host").suppress()
        MATCH = CaselessLiteral("Match").suppress()
        KEY = Word(alphanums)
        VALUE = Word(alphanums + ' ~%*?!._-+/,"')
        paramValueDef = SkipTo("#" | lineEnd)
        indentStack = [1]

        HostDecl = (HOST | MATCH) + SEP + VALUE
        paramDef = Dict(Group(~HOST + KEY + SEP + paramValueDef))
        block = indentedBlock(paramDef, indentStack)
        HostBlock = Dict(Group(HostDecl + block))
        Begin = Empty().setParseAction(replaceWith("GLOBAL_OPTIONS"))
        GlobalOptions = Group(ZeroOrMore(Dict(Group(paramDef))))
        try:
            return (Begin + GlobalOptions + OneOrMore(HostBlock)).ignore(pythonStyleComment).parseString(self.raw)
        except ParseException as e:
            print(e)
        return None

The idea is to parse an eventual first unindented block without host definition, and add the keyword "GLOBAL_OPTIONS" to this block in order to have a proper dict.

It seems to work with the parsed object, but not for the conversion .asDict() :

# parsed :
['GLOBAL_OPTIONS', [[['CanonicalizeHostname', 'no']], [['CanonialDomains', 'no']]], ['github.com', [[['User', 'git']], [['IdentityFile', '~/.ssh/id_github']]]]]

# parsed.asDict() : 
{'github.com': [{'User': 'git'}, {'IdentityFile': '~/.ssh/id_github'}]}

The block "GLOBAL_OPTIONS" appears correctly in the object, but is not converted in the resulted dict.
Since I don't know the lib pyparsing very well, there's maybe an easier way to achieve this, and maybe you have a better idea for this, it would be great.

Thanks

Arnaud

Does not follow Include keyword

It would be nice if this could recursively include files listed in the config file

From 7.3p1 and up, there is the Include keyword

     Include
             Include the specified configuration file(s).  Multiple
             pathnames may be specified and each pathname may contain
             glob(7) wildcards and, for user configurations, shell-like
             ‘~’ references to user home directories.  Wildcards will be
             expanded and processed in lexical order.  Files without
             absolute paths are assumed to be in ~/.ssh if included in a
             user configuration file or /etc/ssh if included from the
             system configuration file.  Include directive may appear
             inside a Match or Host block to perform conditional
             inclusion.

Source: ssh_config(5).

How does `ssh-config update` work?

I tried reading through the source, but it is somewhat confusing.

On running:

ssh-config update
Traceback (most recent call last):
  File "/miniconda3/envs/b37/bin/ssh-config", line 10, in <module>
    sys.exit(main())
  File "/miniconda3/envs/b37/lib/python3.7/site-packages/ssh_config/cli.py", line 98, in main
    argv[1:], options_first=True, version="ssh_config %s" % __version__
  File "/miniconda3/envs/b37/lib/python3.7/site-packages/ssh_config/cli.py", line 72, in __init__
    command_cls = getattr(commands, command_name)
AttributeError: module 'ssh_config.commands' has no attribute 'Update'

There seems to also be no docs and no -h command for subcommands.

Fix "KeyError: 'No'" for "No" values

It is better to change the line at

return convert[value]

to the following. Otherwise, "No" values would run into KeyError: 'No' errors.

convert[value.lower()]

I suggest the code to look like

def yes_or_no(value: str) -> bool:
    """Convert 'yes' or 'no' to True or False
    Args:
        value (str): The string containing 'yes' or 'no'
    Returns:
        bool: True if value is 'yes', False if value is 'no'
    """
    if value is None:
        return
    if value.lower() not in ('yes', 'no', 'true', 'false'):
        raise TypeError(f"Yes or No is required: {value}")
    convert = {
        "yes": True,
        "no": False,
        "true": True,
        "false": False,
        True: "yes",
        False: "no",
    }
    return convert[value.lower()]

Otherwise, I would run into errors when reading back the updated config file.

Keys should be case-insensitive

If I parse a file like:

Host myhost
    hostname myhost.mydomain.com

The parsed hosts gets the attribute HostName = None. However SSH_CONFIG(5) indicates that keywords are case insensitive.

pip install fails on 0.0.12

Versions:
python: 2.7.16
pip: 19.1.1

pip install ssh-config
errror:

 Using cached https://files.pythonhosted.org/packages/b3/a2/72ca9d7c0b181b58d462647421ba1531ce3a62ca9b1c8b65c29c3a0349b9/ssh_config-0.0.12.tar.gz
    ERROR: Complete output from command python setup.py egg_info:
    ERROR: Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/2z/k2bsyg654t3bky0c96fntfj80000gn/T/pip-install-_NfBMw/ssh-config/setup.py", line 7, in <module>
        from ssh_config import __version__
      File "ssh_config/__init__.py", line 1, in <module>
        from .client import SSHConfig, Host, EmptySSHConfig
      File "ssh_config/client.py", line 5, in <module>
        from pyparsing import (
    ImportError: No module named pyparsing
    ----------------------------------------
ERROR: Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/2z/k2bsyg654t3bky0c96fntfj80000gn/T/pip-install-_NfBMw/ssh-config/

It appears that this import: https://github.com/haginara/ssh_config/blob/develop/setup.py#L7
is causing the import of client.py which requires pyparsing which is not yet installed in a new environment.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.