From 07a17b442d7d7a397d076babfaa29fd2620921d7 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Thu, 19 Jan 2017 10:54:32 +0000 Subject: Initial commit --- .gitignore | 2 ++ bin/ssh-update-config | 8 ++++++++ example.rb | 36 ++++++++++++++++++++++++++++++++++++ lib/host.rb | 19 +++++++++++++++++++ lib/hosts.rb | 22 ++++++++++++++++++++++ lib/sshconfig.rb | 13 +++++++++++++ readme.textile | 36 ++++++++++++++++++++++++++++++++++++ sshconfig.gemspec | 19 +++++++++++++++++++ 8 files changed, 155 insertions(+) create mode 100644 .gitignore create mode 100755 bin/ssh-update-config create mode 100755 example.rb create mode 100644 lib/host.rb create mode 100644 lib/hosts.rb create mode 100644 lib/sshconfig.rb create mode 100644 readme.textile create mode 100644 sshconfig.gemspec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ecccbd3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.gem +.*.swp diff --git a/bin/ssh-update-config b/bin/ssh-update-config new file mode 100755 index 0000000..e6cfe93 --- /dev/null +++ b/bin/ssh-update-config @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby +require 'sshconfig' +include SSHConfig + +File.open(File.join(ENV["HOME"], ".ssh/config"), "w") do |f| + load File.join(ENV["HOME"], ".ssh/sshconfig") + f.puts $hostlist +end diff --git a/example.rb b/example.rb new file mode 100755 index 0000000..ef72483 --- /dev/null +++ b/example.rb @@ -0,0 +1,36 @@ +# This is ruby +# Lets make a method for later +def old_keys + kexalgorithms "+diffie-hellman-group1-sha1" + hostkeyalgorithms "+ssh-dss" +end + +hosts { + # Simple things + host("example") { + hostname "example.com" + } + host("pi") { + hostname "192.168.3.14" + user "root" + } + + # LOOPS! + # #contrived + # Also, that method from earlier + (1..70).each { |machine| + host("my#{machine}-1") { hostname "mymachine#{machine}-1.example.co.uk" ; old_keys } + host("my#{machine}-2") { hostname "mymachine#{machine}-2.example.co.uk" ; old_keys } + } + + # NO + # Don't do this + # Just remember that every directive is a method + host ('*') { + strictHostKeyChecking NO + userKnownHostsFile "/dev/null" + logLevel "ERROR" + } +} + +# vim: set ft=ruby: diff --git a/lib/host.rb b/lib/host.rb new file mode 100644 index 0000000..90c3e2e --- /dev/null +++ b/lib/host.rb @@ -0,0 +1,19 @@ +module SSHConfig + class Host + def initialize(name, &block) + @name = name + @directives = {} + self.instance_eval(&block) + end + + def method_missing(meth, arg) + @directives[meth.capitalize] = arg + end + + def to_s + "Host #{@name}\n" + + @directives.map { |k, v| "\t#{k} #{v}" }.join("\n") + + "\n" + end + end +end diff --git a/lib/hosts.rb b/lib/hosts.rb new file mode 100644 index 0000000..1a0fc27 --- /dev/null +++ b/lib/hosts.rb @@ -0,0 +1,22 @@ +module SSHConfig + class Hosts + attr_reader :hosts + + def initialize(&block) + @hosts = [] + self.instance_eval(&block) + end + + def merge(morehosts) + @hosts += morehosts.hosts + end + + def host(name) + @hosts << Host.new(name, &Proc.new) + end + + def to_s + @hosts.map(&:to_s).join("\n") + end + end +end diff --git a/lib/sshconfig.rb b/lib/sshconfig.rb new file mode 100644 index 0000000..204a127 --- /dev/null +++ b/lib/sshconfig.rb @@ -0,0 +1,13 @@ +require 'host' +require 'hosts' + +module SSHConfig + YES = "yes" + NO = "no" + + $hostlist = Hosts.new{} + + def hosts + $hostlist.merge(Hosts.new(&Proc.new)) + end +end diff --git a/readme.textile b/readme.textile new file mode 100644 index 0000000..e0c69ea --- /dev/null +++ b/readme.textile @@ -0,0 +1,36 @@ +h1. SSHConfig + +This is a gem which allows you to programatically configure your ~/.ssh/config. + +It's a bit bad, but it works. + +h2. Config file + +Your new file to worry about is ~/.ssh/sshconfig. + +h2. ssh-update-config + +The @ssh-update-config@ command will generate the ~/.ssh/config file for you. The file will be overwritten. + +h2. Directives + +In the block you pass to a host method, any method becomes an sshconfig directive. It's method_missing_madness! + +h2. It's all ruby! + +h3. So write ruby! + +Methods, loops, variables; you name it. + +h3. $hostlist variable + +The grand list of hosts is stored in @$hostlist@. It's a @Hosts@ object. You can touch this. The @hosts {}@ method appends to this list. @$hostlist.host{}@ does the same as @hosts{host{}}@. + +h2. Building + +bc. gem build sshconfig.gemspec + gem install --user-install sshconfig + +h2. Example + +There's an example file, take a look. diff --git a/sshconfig.gemspec b/sshconfig.gemspec new file mode 100644 index 0000000..ea6c5fa --- /dev/null +++ b/sshconfig.gemspec @@ -0,0 +1,19 @@ +Gem::Specification.new do |s| + s.name = 'sshconfig' + s.version = '12' + s.date = '2017-01-11' + s.summary = "SSH Config DSL" + s.description = "A DSL to generate SSH config" + s.authors = ["Nathan Lasseter"] + s.email = 'nathan@bytemark.co.uk' + s.homepage = 'https://github.com/User4574/SSHConfig' + s.files = [ + "lib/sshconfig.rb", + "lib/host.rb", + "lib/hosts.rb", + ] + s.executables = [ + "ssh-update-config" + ] + s.license = 'BSD-2-Clause' +end -- cgit v1.2.1