hiera_server 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []