hiera_server 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5ed7a076f781fbc8934000975e64a1da503978fe
4
+ data.tar.gz: d24759ab5a84cd572020ed9ac57c72571c825937
5
+ SHA512:
6
+ metadata.gz: 215f91afe5a764aa620d3cf3c8acb22b4a95b60d982fc30b5a1ec696273f1efb7771b380641222b372c63841348cb01224cf7fe49ee2e14eabbee40305218a70
7
+ data.tar.gz: 98ee06d660aa47cb037ddef2492bac751c57fcf41508a5989e79a5291b2d6b50a915a06ef1da6c1373abb058add6ac092fda7fbbbb83b677aa33ae035b2cd439
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (C) 2015 Ben Ford <binford2k@gmail.com>
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,118 @@
1
+ # Hiera Server
2
+
3
+ Hiera Server separates the query and the data retrieval into separate processes.
4
+ The *server* portion runs on a remote machine and uses any configured Hiera
5
+ backend to retrieve data. The *client* portion simply runs as a backend on the
6
+ local machine and forwards requests to the server. Facilities are provided to
7
+ configure the data lookup on the server from either end, allowing the server to
8
+ provide data to more than one client using different configurations.
9
+
10
+ Rather than making multiple HTTP requests, the client will send the full scope
11
+ and any relevant configuration to the server as part of a single request. The
12
+ server will perform the data lookup and return a single response.
13
+
14
+ ## Installation
15
+
16
+ Install the gem in the proper GEMPATHs on both the local and remote systems.
17
+
18
+ ### Local system (the Puppet master or machine running `puppet apply`)
19
+
20
+ For the Puppet master to be able to use this gem, you'll need to install it into
21
+ the Puppet master's GEMPATH. If you're using Puppetserver or PE, you'll want to
22
+ install it like such:
23
+
24
+ $ /opt/puppetlabs/bin/puppetserver gem install hiera_server
25
+
26
+ To be able to access it from the command line, as in CLI `hiera` or `puppet apply`,
27
+ you'll need to also install it into the Puppet GEMPATH, such as:
28
+
29
+ $ /opt/puppetlabs/puppet/bin/gem install hiera_server
30
+
31
+ If you're using Passenger or Webrick, you'll only need to install it once, as the
32
+ GEMPATH are typically shared by the master and agent.
33
+
34
+ ### Remote system (the machine running the Hiera server)
35
+
36
+ This machine doesn't necessarily need to be a Puppet master, but it will need Hiera
37
+ properly installed and configured. Simply install the gem into the Puppet GEMPATH.
38
+
39
+ $ /opt/puppetlabs/puppet/bin/gem install hiera_server
40
+
41
+ ## Configuration
42
+
43
+ Configure the server using the `:server` configuration key in your `hiera.yaml`
44
+ on both the server and the client. The only key **required** is the `[:server][:server]`
45
+ key on the **client** side. This is the address of the machine to forward requests
46
+ to.
47
+
48
+ ### Options
49
+
50
+ * Options used by the server
51
+ * `[:server][:port]`
52
+ * The port to run on. Defaults to 8141
53
+ * `[:server][:ssl]`
54
+ * Boolean. Whether to use ssl. Defaults to false simply because I'm lazy for the MVP.
55
+ * `[:server][:logfile]`
56
+ * Where to log. Defaults to '/var/log/hiera_server'
57
+ * `[:server][:pidfile]`
58
+ * Where to save the pidfile. Defaults to '/var/run/hiera_server.pid'
59
+ * The toplevel `:backends` and `:hierarchy` will be used by default, but
60
+ can be overridden by the client.
61
+ * Options used by the client
62
+ * `[:server][:server]`
63
+ * The server to forward lookups too. **Required**.
64
+ * `[:server][:port]`
65
+ * The port the server is running on. Defaults to 8141
66
+ * `[:server][:backends]`
67
+ * If set, this will override the `:backends` setting on the server
68
+ * `[:server][:hierarchy]`
69
+ * If set, this will override or add to the `:hierarchy` on the server
70
+ * `[:server][:hierarchy_override]`
71
+ * Describes how to merge the ':hierarchy' on the server
72
+ * Accepted values are: 'prepend`, 'append', 'replace'
73
+
74
+ ### Example `hiera.yaml` file on the client
75
+
76
+ This will force the server to use the `yaml` backend when servicing requests,
77
+ and will put the `%{clientcert}` at the top of the hierarchy used by the server.
78
+ The server contacted will be `master.puppetlabs.vm` on port `8141`.
79
+
80
+ ---
81
+ :backends:
82
+ - server
83
+
84
+ :yaml:
85
+ :datadir: /etc/puppetlabs/code/hieradata
86
+
87
+ :server:
88
+ :server: master.puppetlabs.vm
89
+ :port: 8141
90
+ :backends:
91
+ - yaml
92
+ :hierarchy:
93
+ - "%{clientcert}"
94
+ :hierarchy_override: prepend
95
+
96
+ :hierarchy:
97
+ - "environments/%{environment}/hieradata/%{osfamily}"
98
+ - "environments/%{environment}/hieradata/%{clientcert}"
99
+ - "environments/%{environment}/hieradata/defaults"
100
+ - defaults
101
+
102
+ ## Running the server
103
+
104
+ The server executable is installed into the standard PATH. For example, if you
105
+ installed it on Puppet Enterprise, the server will be located at
106
+
107
+ $ /opt/puppetlabs/puppet/bin/hiera_server
108
+
109
+ A sample init script is located in the `docs` directory of the gem.
110
+
111
+ ## Disclaimer
112
+
113
+ This is currently a proof of concept and was written in just a few hours. You get what you pay for.
114
+
115
+ Contact
116
+ -------
117
+
118
+ binford2k@gmail.com
@@ -0,0 +1,73 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'fileutils'
5
+ require 'sinatra/base'
6
+ require 'webrick'
7
+ require 'webrick/https'
8
+ require 'openssl'
9
+ require 'resolv'
10
+ require 'json'
11
+
12
+ require 'hiera'
13
+ require 'hiera/util'
14
+ require 'optparse'
15
+
16
+ require 'hiera_server'
17
+
18
+ $config = YAML.load_file(File.join(Hiera::Util.config_dir, 'hiera.yaml'))
19
+ $config[:server] ||= {}
20
+ $config[:server][:bind] ||= '0.0.0.0'
21
+ $config[:server][:port] ||= '8141'
22
+ $config[:server][:ssl] ||= false
23
+ $config[:server][:logfile] ||= '/var/log/hiera_server'
24
+ $config[:server][:pidfile] ||= '/var/run/hiera_server.pid'
25
+
26
+ optparse = OptionParser.new { |opts|
27
+ opts.banner = "Usage : #{File.basename($PROGRAM_NAME)}"
28
+
29
+ opts.on("-d", "--debug", "Display extra debugging information.") do
30
+ require 'pry'
31
+ $config[:server][:debug] = true
32
+ end
33
+
34
+ opts.separator('')
35
+
36
+ opts.on("-h", "--help", "Displays this help") do
37
+ puts opts
38
+ exit
39
+ end
40
+ }
41
+ optparse.parse!
42
+
43
+ if $config[:server][:debug]
44
+ servertype = WEBrick::SimpleServer
45
+ loglevel = WEBrick::Log::DEBUG
46
+ else
47
+ servertype = WEBrick::Daemon
48
+ loglevel = WEBrick::Log::INFO
49
+ end
50
+
51
+ options = {
52
+ :Host => $config[:server][:bind],
53
+ :Port => $config[:server][:port],
54
+ :Logger => WEBrick::Log::new($config[:server][:logfile], loglevel),
55
+ :ServerType => servertype,
56
+ :SSLEnable => $config[:server][:ssl],
57
+ :StartCallback => Proc.new { File.open($config[:server][:pidfile], 'w') {|f| f.write Process.pid } },
58
+ }
59
+ if $config[:server][:ssl] then
60
+ options[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
61
+ options[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.open("#{$config[:server][:public_key]}").read)
62
+ options[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.open("#{$config[:server][:private_key]}").read)
63
+ options[:SSLCertName] = [ [ "CN",WEBrick::Utils::getservername ] ]
64
+ end
65
+
66
+ Rack::Handler::WEBrick.run(HieraServer, options) do |server|
67
+ [:INT, :TERM].each do |sig|
68
+ trap(sig) do
69
+ server.stop
70
+ FileUtils.rm $config[:server][:pidfile]
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,86 @@
1
+ #!/bin/bash
2
+ # webhook Init script for running the hiera server daemon
3
+ #
4
+ # Author: Ben Ford <binford2k@gmail.com
5
+ #
6
+ # chkconfig: 2345 98 02
7
+ #
8
+ # description: Init script for running the hiera server daemon
9
+ # processname: hiera_server
10
+
11
+ # This is a pretty cruddy init script.
12
+
13
+ # source function library
14
+ #. /etc/rc.d/init.d/functions
15
+
16
+ PATH=/opt/puppetlabs/puppet/bin/:/usr/local/bin:$PATH
17
+ PID=$([ -f /var/run/hiera_server.pid ] && cat /var/run/hiera_server.pid)
18
+
19
+ printstat()
20
+ {
21
+ if [ "$1" != "" ]
22
+ then
23
+ echo $1
24
+ else
25
+ if [ $RETVAL -eq 0 ]; then echo "OK"; else echo "FAIL"; fi
26
+ fi
27
+ }
28
+
29
+ start()
30
+ {
31
+ echo -n $"Starting Hiera Server: "
32
+ hiera_server
33
+ RETVAL=$?
34
+ printstat
35
+ }
36
+
37
+ stop()
38
+ {
39
+ echo -n $"Stopping Hiera Server: "
40
+ if [ "${PID}" == "" ]
41
+ then
42
+ printstat 'not running'
43
+ RETVAL=2
44
+ else
45
+ kill ${PID}
46
+ RETVAL=$?
47
+ sleep 3 # it would be nice if webrick didn't take so long to shut down
48
+ printstat
49
+ fi
50
+ }
51
+
52
+ status()
53
+ {
54
+ if [ "${PID}" != "" ]
55
+ then
56
+ echo $"Hiera Server is running."
57
+ RETVAL=0
58
+ else
59
+ echo $"Hiera Server is stopped."
60
+ RETVAL=1
61
+ fi
62
+ }
63
+
64
+ restart() {
65
+ stop
66
+ start
67
+ }
68
+
69
+ case "$1" in
70
+ start)
71
+ start
72
+ ;;
73
+ stop)
74
+ stop
75
+ ;;
76
+ restart)
77
+ restart
78
+ ;;
79
+ status)
80
+ status
81
+ ;;
82
+ *)
83
+ echo $"Usage: $0 {start|stop|restart|status}"
84
+ RETVAL=10
85
+ esac
86
+ exit $RETVAL
@@ -0,0 +1,67 @@
1
+ require 'json'
2
+ require 'openssl'
3
+ require "net/https" # use instead of rest-client so we can set SSL options
4
+
5
+ class Hiera
6
+ module Backend
7
+ class Server_backend
8
+ def initialize
9
+ Config[:server][:backends] ||= Config[:backends]
10
+ Config[:server][:hierarchy] ||= Config[:hierarchy]
11
+ Config[:server][:port] ||= '8141'
12
+
13
+ # I think this connection can be reused like this. If not, move it to the query and make it local
14
+ @http = Net::HTTP.new(Config[:server][:server], Config[:server][:port])
15
+
16
+ if Config[:server][:ssl]
17
+ @http.use_ssl = true
18
+ @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
19
+
20
+ store = OpenSSL::X509::Store.new
21
+ store.add_cert(OpenSSL::X509::Certificate.new(File.read(Config[:server][:ca_cert])))
22
+ @http.cert_store = store
23
+
24
+ @http.key = OpenSSL::PKey::RSA.new(File.read(Config[:server][:public_key]))
25
+ @http.cert = OpenSSL::X509::Certificate.new(File.read(Config[:server][:private_key]))
26
+ else
27
+ @http.use_ssl = false
28
+ end
29
+
30
+ debug ("Loaded HieraServer Backend")
31
+ end
32
+
33
+ def debug(msg)
34
+ Hiera.debug("[HieraServer]: #{msg}")
35
+ end
36
+
37
+ def warn(msg)
38
+ Hiera.warn("[HieraServer]: #{msg}")
39
+ end
40
+
41
+ def lookup(key, scope, order_override, resolution_type, context)
42
+ debug("Looking up '#{key}', resolution type is #{resolution_type}")
43
+
44
+ path = "/#{resolution_type.to_s}/#{key}"
45
+ request = Net::HTTP::Post.new(path, initheader = {'Content-Type' =>'application/json'})
46
+
47
+ request.body = {
48
+ "scope" => scope,
49
+ "backends" => Config[:server][:backends],
50
+ "hierarchy" => Config[:server][:hierarchy],
51
+ "hierarchy_override" => Config[:server][:hierarchy_override],
52
+ }.to_json
53
+
54
+ # make the request
55
+ response = JSON.parse(@http.request(request).body)
56
+
57
+ if response.keys.include? 'value'
58
+ response['value']
59
+ else
60
+ warn response['error']
61
+ debug response['trace']
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,78 @@
1
+ require 'rubygems'
2
+ require 'sinatra/base'
3
+ require 'json'
4
+
5
+ require 'hiera'
6
+
7
+ class HieraServer < Sinatra::Base
8
+
9
+ get '/' do
10
+ raise Sinatra::NotFound
11
+ end
12
+
13
+ post '/:type/:key' do |type, key|
14
+ begin
15
+ request.body.rewind
16
+ body = JSON.parse(request.body.read)
17
+ hiera = Hiera.new(:config => munged_config(body))
18
+
19
+ if type == 'merge'
20
+ value = hiera.lookup(key, nil, body['scope'], nil, body['merge'])
21
+ else
22
+ value = hiera.lookup(key, nil, body['scope'], nil, type.to_sym)
23
+ end
24
+ # Must rescue Exception because that's what Hiera raises.
25
+ rescue Exception => e
26
+ binding.pry if $config[:server][:debug]
27
+ raise e if [Interrupt, SignalException].include? e.class
28
+ {
29
+ 'error' => e.message,
30
+ 'trace' => e.backtrace,
31
+ }.to_json
32
+ end
33
+
34
+ {'value' => value}.to_json
35
+ end
36
+
37
+ not_found do
38
+ halt 404, "You shall not pass! (page not found)\n"
39
+ end
40
+
41
+ helpers do
42
+ def protected!
43
+ unless authorized?
44
+ response['WWW-Authenticate'] = %(Basic realm="Restricted Area")
45
+ throw(:halt, [401, "Not authorized\n"])
46
+ end
47
+ end #end protected!
48
+
49
+ def authorized?
50
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
51
+ @auth.provided? && @auth.basic? && @auth.credentials &&
52
+ @auth.credentials == [$config['user'],$config['pass']]
53
+ end #end authorized?
54
+
55
+ def munged_config(data)
56
+ config = $config.dup
57
+
58
+ # let the client configure the backend to use
59
+ config[:backends] = data['backends'] if data.include? 'backends'
60
+
61
+ # munge the hierarchy as needed
62
+ case data['hierarchy_override']
63
+ when 'prepend'
64
+ config[:hierarchy].unshift data['hierarchy']
65
+ when 'append'
66
+ config[:hierarchy] << data['hierarchy']
67
+ when 'replace'
68
+ config[:hierarchy] = data['hierarchy']
69
+ end
70
+
71
+ # now copy in arbitrary config settings that we're not already handling
72
+ config[:server] = data.reject {|item| ['backend', 'hierarchy', 'scope', 'merge'].include? item }
73
+
74
+ config
75
+ end
76
+
77
+ end
78
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hiera_server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben Ford
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json_pure
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: |2
42
+ Hiera Server separates the query and the data retrieval into separate processes.
43
+ The *server* portion runs on a remote machine and uses any configured Hiera backend
44
+ to retrieve data. The *client* portion simply runs as a backend on the local machine.
45
+
46
+ Facilities are provided to configure the data lookup on the server from either end.
47
+ See README.md for more information.
48
+ email: binford2k@gmail.com
49
+ executables:
50
+ - hiera_server
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - README.md
55
+ - LICENSE
56
+ - bin/hiera_server
57
+ - lib/hiera/backend/server_backend.rb
58
+ - lib/hiera_server.rb
59
+ - doc/hiera_server.init.example
60
+ homepage: https://github.com/binford2k/hiera_server
61
+ licenses:
62
+ - Apache 2.0
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.0.14
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: Provides a remote server for Hiera lookups and a backend client.
84
+ test_files: []