summaryrefslogtreecommitdiffstats
path: root/lib/puppet/networkclient.rb
blob: 31bc9a9dd2298a5e950039aea2732674910572be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require 'puppet'
require 'puppet/sslcertificates'
require 'puppet/type'
require 'facter'
require 'openssl'
require 'puppet/transaction'
require 'puppet/transportable'
require 'puppet/metric'
require 'puppet/daemon'
require 'puppet/server'
require 'puppet/base64'

$noclientnetworking = false
begin
    require 'webrick'
    require 'cgi'
    require 'xmlrpc/client'
    require 'xmlrpc/server'
    require 'yaml'
rescue LoadError => detail
    $noclientnetworking = detail
    raise Puppet::Error, "You must have the Ruby XMLRPC, CGI, and Webrick libraries installed"
end

module Puppet
    class NetworkClientError < RuntimeError; end
    class ClientError < RuntimeError; end
    #---------------------------------------------------------------
    if $noclientnetworking
        Puppet.err "Could not load client network libs: %s" % $noclientnetworking
    else
        class NetworkClient < XMLRPC::Client
            #include Puppet::Daemon

            # add the methods associated with each namespace
            Puppet::Server::Handler.each { |handler|
                interface = handler.interface
                namespace = interface.prefix

                interface.methods.each { |ary|
                    method = ary[0]
                    Puppet.info "Defining %s.%s" % [namespace, method]
                    self.send(:define_method,method) { |*args|
                        #Puppet.info "Calling %s" % method
                        #Puppet.info "peer cert is %s" % @http.peer_cert
                        #Puppet.info "cert is %s" % @http.cert
                        begin
                            call("%s.%s" % [namespace, method.to_s],*args)
                        rescue OpenSSL::SSL::SSLError => detail
                            #Puppet.err "Could not call %s.%s: Untrusted certificates" %
                            #    [namespace, method]
                            raise NetworkClientError,
                                "Certificates were not trusted"
                        rescue XMLRPC::FaultException => detail
                            #Puppet.err "Could not call %s.%s: %s" %
                            #    [namespace, method, detail.faultString]
                            #raise NetworkClientError,
                            #    "XMLRPC Error: %s" % detail.faultString
                            raise NetworkClientError, detail.faultString
                        rescue Errno::ECONNREFUSED => detail
                            msg = "Could not connect to %s on port %s" % [@host, @port]
                            #Puppet.err msg
                            raise NetworkClientError, msg
                        rescue SocketError => detail
                            Puppet.err "Could not find server %s" % @puppetserver
                            exit(12)
                        rescue => detail
                            Puppet.err "Could not call %s.%s: %s" %
                                [namespace, method, detail.inspect]
                            #raise NetworkClientError.new(detail.to_s)
                            raise
                        end
                    }
                }
            }

            def ca_file=(cafile)
                @http.ca_file = cafile
                store = OpenSSL::X509::Store.new
                cacert = OpenSSL::X509::Certificate.new(
                    File.read(cafile)
                )
                store.add_cert(cacert) 
                store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT
                @http.cert_store = store
            end

            def cert=(cert)
                #Puppet.debug "Adding certificate"
                @http.cert = cert
                @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
            end

            def key=(key)
                @http.key = key
            end

            def initialize(hash)
                hash[:Path] ||= "/RPC2"
                hash[:Server] ||= "localhost"
                hash[:Port] ||= Puppet[:masterport]

                @puppetserver = hash[:Server]

                super(
                    hash[:Server],
                    hash[:Path],
                    hash[:Port],
                    nil, # proxy_host
                    nil, # proxy_port
                    nil, # user
                    nil, # password
                    true # use_ssl
                )

                if hash[:Certificate]
                    self.cert = hash[:Certificate]
                else
                    Puppet.err "No certificate; running with reduced functionality."
                end

                if hash[:Key]
                    self.key = hash[:Key]
                end

                if hash[:CAFile]
                    self.ca_file = hash[:CAFile]
                end

                # from here, i need to add the key, cert, and ca cert
                # and reorgize how i start the client
            end

            def local
                false
            end
        end
    end
end

# $Id$