a7ea788391964a02670128a76a498b32d3eda762
2 Copyright 2007, Red Hat, Inc
5 This software may be freely redistributed under the terms of the GNU
6 general public license.
8 You should have received a copy of the GNU General Public License
9 along with this program; if not, write to the Free Software
10 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 from func
import certs
25 from func
.config
import read_config
26 from func
.commonconfig
import FuncdConfig
27 from func
import logger
29 # "localhost" is a lame hostname to use for a key, so try to get
30 # a more meaningful hostname. We do this by connecting to the certmaster
31 # and seeing what interface/ip it uses to make that connection, and looking
32 # up the hostname for that.
35 # FIXME: this code ignores http proxies (which granted, we don't
36 # support elsewhere either. It also hardcodes the port number
37 # for the certmaster for now
39 hostname
= socket
.gethostname()
41 ip
= socket
.gethostbyname(hostname
)
48 config_file
= '/etc/func/minion.conf'
49 config
= read_config(config_file
, FuncdConfig
)
51 server
= config
.certmaster
57 s
.connect((server
, port
))
58 (intf
, port
) = s
.getsockname()
59 hostname
= socket
.gethostbyaddr(intf
)[0]
69 def create_minion_keys():
70 config_file
= '/etc/func/minion.conf'
71 config
= read_config(config_file
, FuncdConfig
)
72 cert_dir
= config
.cert_dir
73 master_uri
= 'http://%s:51235/' % config
.certmaster
77 raise codes
.FuncException("Could not determine a hostname other than localhost")
79 key_file
= '%s/%s.pem' % (cert_dir
, hn
)
80 csr_file
= '%s/%s.csr' % (cert_dir
, hn
)
81 cert_file
= '%s/%s.cert' % (cert_dir
, hn
)
82 ca_cert_file
= '%s/ca.cert' % cert_dir
85 if os
.path
.exists(cert_file
) and os
.path
.exists(ca_cert_file
):
90 if not os
.path
.exists(cert_dir
):
92 if not os
.path
.exists(key_file
):
93 keypair
= certs
.make_keypair(dest
=key_file
)
94 if not os
.path
.exists(csr_file
):
96 keypair
= certs
.retrieve_key_from_file(key_file
)
97 csr
= certs
.make_csr(keypair
, dest
=csr_file
)
100 raise codes
.FuncException
, "Could not create local keypair or csr for minion funcd session"
103 log
= logger
.Logger().logger
106 log
.debug("submitting CSR to certmaster %s" % master_uri
)
107 result
, cert_string
, ca_cert_string
= submit_csr_to_master(csr_file
, master_uri
)
108 except socket
.gaierror
, e
:
109 raise codes
.FuncException
, "Could not locate certmaster at %s" % master_uri
111 # logging here would be nice
113 log
.warning("no response from certmaster %s, sleeping 10 seconds" % master_uri
)
118 log
.debug("received certificate from certmaster %s, storing" % master_uri
)
119 cert_fd
= os
.open(cert_file
, os
.O_RDWR|os
.O_CREAT
, 0644)
120 os
.write(cert_fd
, cert_string
)
123 ca_cert_fd
= os
.open(ca_cert_file
, os
.O_RDWR|os
.O_CREAT
, 0644)
124 os
.write(ca_cert_fd
, ca_cert_string
)
127 def submit_csr_to_master(csr_file
, master_uri
):
129 gets us our cert back from the certmaster.wait_for_cert() method
130 takes csr_file as path location and master_uri
131 returns Bool, str(cert), str(ca_cert)
136 s
= xmlrpclib
.ServerProxy(master_uri
)
138 return s
.wait_for_cert(csr
)
141 # this is kind of handy, so keep it around for now
142 # but we really need to fix out server side logging and error
143 # reporting so we don't need it
145 x
= traceback
.extract_stack()
146 bar
= string
.join(traceback
.format_list(x
))
150 def daemonize(pidfile
=None):
152 Daemonize this process with the UNIX double-fork trick.
153 Writes the new PID to the provided file name if not None.
166 if pidfile
is not None:
167 open(pidfile
, "w").write(str(pid
))
170 def get_acls_from_config(acldir
='/etc/func/minion-acl.d'):
172 takes a dir of .acl files
173 returns a dict of hostname+hash = [methods, to, run]
178 if not os
.path
.exists(acldir
):
179 print 'acl dir does not exist: %s' % acldir
182 # get the set of files
183 acl_glob
= '%s/*.acl' % acldir
184 files
= glob
.glob(acl_glob
)
186 for acl_file
in files
:
189 fo
= open(acl_file
, 'r')
190 except (IOError, OSError), e
:
191 print 'cannot open acl config file: %s - %s' % (acl_file
, e
)
194 for line
in fo
.readlines():
195 if line
.startswith('#'): continue
196 if line
.strip() == '': continue
197 line
= line
.replace('\n', '')
198 (host
, methods
) = line
.split('=')
199 host
= host
.strip().lower()
200 methods
= methods
.strip()
201 methods
= methods
.replace(',',' ')
202 methods
= methods
.split()
203 if not acls
.has_key(host
):
205 acls
[host
].extend(methods
)