summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Likins <alikins@redhat.com>2008-07-24 12:32:50 -0400
committerAdrian Likins <alikins@redhat.com>2008-07-24 12:32:50 -0400
commit826fdd377c5a7f49e6ca707838d6bee2dbff731e (patch)
treebf7ad884b59ec388dfea674fb1d4c2f03f6859a4
parent27133ae4811dd5bb7d86683714a637ca2fdca053 (diff)
downloadfunc-826fdd377c5a7f49e6ca707838d6bee2dbff731e.tar.gz
func-826fdd377c5a7f49e6ca707838d6bee2dbff731e.tar.xz
func-826fdd377c5a7f49e6ca707838d6bee2dbff731e.zip
remove func/certs.py, func/config.py, and func/minion/utils.py
-rw-r--r--func/certs.py139
-rw-r--r--func/config.py478
-rwxr-xr-xfunc/minion/utils.py95
3 files changed, 0 insertions, 712 deletions
diff --git a/func/certs.py b/func/certs.py
deleted file mode 100644
index 4d6bf15..0000000
--- a/func/certs.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Library General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Copyright (c) 2007 Red Hat, inc
-#- Written by Seth Vidal skvidal @ fedoraproject.org
-
-from OpenSSL import crypto
-import socket
-import os
-import utils
-
-def_country = 'UN'
-def_state = 'FC'
-def_local = 'Func-ytown'
-def_org = 'func'
-def_ou = 'slave-key'
-
-
-def make_keypair(dest=None):
- pkey = crypto.PKey()
- pkey.generate_key(crypto.TYPE_RSA, 2048)
- if dest:
- destfd = os.open(dest, os.O_RDWR|os.O_CREAT, 0600)
- os.write(destfd, (crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)))
- os.close(destfd)
-
- return pkey
-
-
-def make_csr(pkey, dest=None, cn=None):
- req = crypto.X509Req()
- req.get_subject()
- subj = req.get_subject()
- subj.C = def_country
- subj.ST = def_state
- subj.L = def_local
- subj.O = def_org
- subj.OU = def_ou
- if cn:
- subj.CN = cn
- else:
- subj.CN = utils.get_hostname()
- subj.emailAddress = 'root@%s' % subj.CN
-
- req.set_pubkey(pkey)
- req.sign(pkey, 'md5')
- if dest:
- destfd = os.open(dest, os.O_RDWR|os.O_CREAT, 0644)
- os.write(destfd, crypto.dump_certificate_request(crypto.FILETYPE_PEM, req))
- os.close(destfd)
-
- return req
-
-
-def retrieve_key_from_file(keyfile):
- fo = open(keyfile, 'r')
- buf = fo.read()
- keypair = crypto.load_privatekey(crypto.FILETYPE_PEM, buf)
- return keypair
-
-
-def retrieve_csr_from_file(csrfile):
- fo = open(csrfile, 'r')
- buf = fo.read()
- csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, buf)
- return csrreq
-
-
-def retrieve_cert_from_file(certfile):
- fo = open(certfile, 'r')
- buf = fo.read()
- cert = crypto.load_certificate(crypto.FILETYPE_PEM, buf)
- return cert
-
-
-def create_ca(CN="Func Certificate Authority", ca_key_file=None, ca_cert_file=None):
- cakey = make_keypair(dest=ca_key_file)
- careq = make_csr(cakey, cn=CN)
- cacert = crypto.X509()
- cacert.set_serial_number(0)
- cacert.gmtime_adj_notBefore(0)
- cacert.gmtime_adj_notAfter(60*60*24*365*10) # 10 yrs - hard to beat this kind of cert!
- cacert.set_issuer(careq.get_subject())
- cacert.set_subject(careq.get_subject())
- cacert.set_pubkey(careq.get_pubkey())
- cacert.sign(cakey, 'md5')
- if ca_cert_file:
- destfo = open(ca_cert_file, 'w')
- destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert))
- destfo.close()
-
-
-def _get_serial_number(cadir):
- serial = '%s/serial.txt' % cadir
- i = 1
- if os.path.exists(serial):
- f = open(serial, 'r').read()
- f = f.replace('\n','')
- try:
- i = int(f)
- i+=1
- except ValueError, e:
- i = 1
-
- _set_serial_number(cadir, i)
- return i
-
-
-def _set_serial_number(cadir, last):
- serial = '%s/serial.txt' % cadir
- f = open(serial, 'w')
- f.write(str(last) + '\n')
- f.close()
-
-
-def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
- cert = crypto.X509()
- cert.set_serial_number(_get_serial_number(cadir))
- cert.gmtime_adj_notBefore(0)
- cert.gmtime_adj_notAfter(60*60*24*365*10) # 10 yrs - hard to beat this kind of cert!
- cert.set_issuer(cacert.get_subject())
- cert.set_subject(csr.get_subject())
- cert.set_pubkey(csr.get_pubkey())
- cert.sign(cakey, 'md5')
- if slave_cert_file:
- destfo = open(slave_cert_file, 'w')
- destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
- destfo.close()
- return cert
diff --git a/func/config.py b/func/config.py
deleted file mode 100644
index e859f4a..0000000
--- a/func/config.py
+++ /dev/null
@@ -1,478 +0,0 @@
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Library General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Copyright 2002 Duke University
-# filched from yum - menno smits wrote this - he rocks
-
-
-import os
-import sys
-import warnings
-import copy
-import urlparse
-from ConfigParser import NoSectionError, NoOptionError, ConfigParser
-from ConfigParser import ParsingError
-import exceptions
-
-CONFIG_FILE = "/etc/certmaster/certmaster.conf"
-
-class ConfigError(exceptions.Exception):
- def __init__(self, value=None):
- exceptions.Exception.__init__(self)
- self.value = value
- def __str__(self):
- return "%s" %(self.value,)
-
-
-class Option(object):
- '''
- This class handles a single Yum configuration file option. Create
- subclasses for each type of supported configuration option.
-
- Python descriptor foo (__get__ and __set__) is used to make option
- definition easy and consise.
- '''
-
- def __init__(self, default=None):
- self._setattrname()
- self.inherit = False
- self.default = default
-
- def _setattrname(self):
- '''Calculate the internal attribute name used to store option state in
- configuration instances.
- '''
- self._attrname = '__opt%d' % id(self)
-
- def __get__(self, obj, objtype):
- '''Called when the option is read (via the descriptor protocol).
-
- @param obj: The configuration instance to modify.
- @param objtype: The type of the config instance (not used).
- @return: The parsed option value or the default value if the value
- wasn't set in the configuration file.
- '''
- if obj is None:
- return self
-
- return getattr(obj, self._attrname, None)
-
- def __set__(self, obj, value):
- '''Called when the option is set (via the descriptor protocol).
-
- @param obj: The configuration instance to modify.
- @param value: The value to set the option to.
- @return: Nothing.
- '''
- # Only try to parse if its a string
- if isinstance(value, basestring):
- try:
- value = self.parse(value)
- except ValueError, e:
- # Add the field name onto the error
- raise ValueError('Error parsing %r: %s' % (value, str(e)))
-
- setattr(obj, self._attrname, value)
-
- def setup(self, obj, name):
- '''Initialise the option for a config instance.
- This must be called before the option can be set or retrieved.
-
- @param obj: BaseConfig (or subclass) instance.
- @param name: Name of the option.
- '''
- setattr(obj, self._attrname, copy.copy(self.default))
-
- def clone(self):
- '''Return a safe copy of this Option instance
- '''
- new = copy.copy(self)
- new._setattrname()
- return new
-
- def parse(self, s):
- '''Parse the string value to the Option's native value.
-
- @param s: Raw string value to parse.
- @return: Validated native value.
-
- Will raise ValueError if there was a problem parsing the string.
- Subclasses should override this.
- '''
- return s
-
- def tostring(self, value):
- '''Convert the Option's native value to a string value.
-
- @param value: Native option value.
- @return: String representation of input.
-
- This does the opposite of the parse() method above.
- Subclasses should override this.
- '''
- return str(value)
-
-
-def Inherit(option_obj):
- '''Clone an Option instance for the purposes of inheritance. The returned
- instance has all the same properties as the input Option and shares items
- such as the default value. Use this to avoid redefinition of reused
- options.
-
- @param option_obj: Option instance to inherit.
- @return: New Option instance inherited from the input.
- '''
- new_option = option_obj.clone()
- new_option.inherit = True
- return new_option
-
-
-class ListOption(Option):
-
- def __init__(self, default=None):
- if default is None:
- default = []
- super(ListOption, self).__init__(default)
-
- def parse(self, s):
- """Converts a string from the config file to a workable list
-
- Commas and spaces are used as separators for the list
- """
- # we need to allow for the '\n[whitespace]' continuation - easier
- # to sub the \n with a space and then read the lines
- s = s.replace('\n', ' ')
- s = s.replace(',', ' ')
- return s.split()
-
- def tostring(self, value):
- return '\n '.join(value)
-
-
-class UrlOption(Option):
- '''
- This option handles lists of URLs with validation of the URL scheme.
- '''
-
- def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https'),
- allow_none=False):
- super(UrlOption, self).__init__(default)
- self.schemes = schemes
- self.allow_none = allow_none
-
- def parse(self, url):
- url = url.strip()
-
- # Handle the "_none_" special case
- if url.lower() == '_none_':
- if self.allow_none:
- return None
- else:
- raise ValueError('"_none_" is not a valid value')
-
- # Check that scheme is valid
- (s,b,p,q,f,o) = urlparse.urlparse(url)
- if s not in self.schemes:
- raise ValueError('URL must be %s not "%s"' % (self._schemelist(), s))
-
- return url
-
- def _schemelist(self):
- '''Return a user friendly list of the allowed schemes
- '''
- if len(self.schemes) < 1:
- return 'empty'
- elif len(self.schemes) == 1:
- return self.schemes[0]
- else:
- return '%s or %s' % (', '.join(self.schemes[:-1]), self.schemes[-1])
-
-
-class UrlListOption(ListOption):
- '''
- Option for handling lists of URLs with validation of the URL scheme.
- '''
-
- def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https')):
- super(UrlListOption, self).__init__(default)
-
- # Hold a UrlOption instance to assist with parsing
- self._urloption = UrlOption(schemes=schemes)
-
- def parse(self, s):
- out = []
- for url in super(UrlListOption, self).parse(s):
- out.append(self._urloption.parse(url))
- return out
-
-
-class IntOption(Option):
- def parse(self, s):
- try:
- return int(s)
- except (ValueError, TypeError), e:
- raise ValueError('invalid integer value')
-
-
-class BoolOption(Option):
- def parse(self, s):
- s = s.lower()
- if s in ('0', 'no', 'false'):
- return False
- elif s in ('1', 'yes', 'true'):
- return True
- else:
- raise ValueError('invalid boolean value')
-
- def tostring(self, value):
- if value:
- return "1"
- else:
- return "0"
-
-
-class FloatOption(Option):
- def parse(self, s):
- try:
- return float(s.strip())
- except (ValueError, TypeError):
- raise ValueError('invalid float value')
-
-
-class SelectionOption(Option):
- '''Handles string values where only specific values are allowed
- '''
- def __init__(self, default=None, allowed=()):
- super(SelectionOption, self).__init__(default)
- self._allowed = allowed
-
- def parse(self, s):
- if s not in self._allowed:
- raise ValueError('"%s" is not an allowed value' % s)
- return s
-
-class BytesOption(Option):
-
- # Multipliers for unit symbols
- MULTS = {
- 'k': 1024,
- 'm': 1024*1024,
- 'g': 1024*1024*1024,
- }
-
- def parse(self, s):
- """Parse a friendly bandwidth option to bytes
-
- The input should be a string containing a (possibly floating point)
- number followed by an optional single character unit. Valid units are
- 'k', 'M', 'G'. Case is ignored.
-
- Valid inputs: 100, 123M, 45.6k, 12.4G, 100K, 786.3, 0
- Invalid inputs: -10, -0.1, 45.6L, 123Mb
-
- Return value will always be an integer
-
- 1k = 1024 bytes.
-
- ValueError will be raised if the option couldn't be parsed.
- """
- if len(s) < 1:
- raise ValueError("no value specified")
-
- if s[-1].isalpha():
- n = s[:-1]
- unit = s[-1].lower()
- mult = self.MULTS.get(unit, None)
- if not mult:
- raise ValueError("unknown unit '%s'" % unit)
- else:
- n = s
- mult = 1
-
- try:
- n = float(n)
- except ValueError:
- raise ValueError("couldn't convert '%s' to number" % n)
-
- if n < 0:
- raise ValueError("bytes value may not be negative")
-
- return int(n * mult)
-
-
-class ThrottleOption(BytesOption):
-
- def parse(self, s):
- """Get a throttle option.
-
- Input may either be a percentage or a "friendly bandwidth value" as
- accepted by the BytesOption.
-
- Valid inputs: 100, 50%, 80.5%, 123M, 45.6k, 12.4G, 100K, 786.0, 0
- Invalid inputs: 100.1%, -4%, -500
-
- Return value will be a int if a bandwidth value was specified or a
- float if a percentage was given.
-
- ValueError will be raised if input couldn't be parsed.
- """
- if len(s) < 1:
- raise ValueError("no value specified")
-
- if s[-1] == '%':
- n = s[:-1]
- try:
- n = float(n)
- except ValueError:
- raise ValueError("couldn't convert '%s' to number" % n)
- if n < 0 or n > 100:
- raise ValueError("percentage is out of range")
- return n / 100.0
- else:
- return BytesOption.parse(self, s)
-
-
-class BaseConfig(object):
- '''
- Base class for storing configuration definitions. Subclass when creating
- your own definitons.
- '''
-
- def __init__(self):
- self._section = None
-
- for name in self.iterkeys():
- option = self.optionobj(name)
- option.setup(self, name)
-
- def __str__(self):
- out = []
- out.append('[%s]' % self._section)
- for name, value in self.iteritems():
- out.append('%s: %r' % (name, value))
- return '\n'.join(out)
-
- def populate(self, parser, section, parent=None):
- '''Set option values from a INI file section.
-
- @param parser: ConfParser instance (or subclass)
- @param section: INI file section to read use.
- @param parent: Optional parent BaseConfig (or subclass) instance to use
- when doing option value inheritance.
- '''
- self.cfg = parser
- self._section = section
-
- for name in self.iterkeys():
- option = self.optionobj(name)
- value = None
- try:
- value = parser.get(section, name)
- except (NoSectionError, NoOptionError):
- # No matching option in this section, try inheriting
- if parent and option.inherit:
- value = getattr(parent, name)
-
- if value is not None:
- setattr(self, name, value)
-
- def optionobj(cls, name):
- '''Return the Option instance for the given name
- '''
- obj = getattr(cls, name, None)
- if isinstance(obj, Option):
- return obj
- else:
- raise KeyError
- optionobj = classmethod(optionobj)
-
- def isoption(cls, name):
- '''Return True if the given name refers to a defined option
- '''
- try:
- cls.optionobj(name)
- return True
- except KeyError:
- return False
- isoption = classmethod(isoption)
-
- def iterkeys(self):
- '''Yield the names of all defined options in the instance.
- '''
- for name, item in self.iteritems():
- yield name
-
- def iteritems(self):
- '''Yield (name, value) pairs for every option in the instance.
-
- The value returned is the parsed, validated option value.
- '''
- # Use dir() so that we see inherited options too
- for name in dir(self):
- if self.isoption(name):
- yield (name, getattr(self, name))
-
- def write(self, fileobj, section=None, always=()):
- '''Write out the configuration to a file-like object
-
- @param fileobj: File-like object to write to
- @param section: Section name to use. If not-specified the section name
- used during parsing will be used.
- @param always: A sequence of option names to always write out.
- Options not listed here will only be written out if they are at
- non-default values. Set to None to dump out all options.
- '''
- # Write section heading
- if section is None:
- if self._section is None:
- raise ValueError("not populated, don't know section")
- section = self._section
-
- # Updated the ConfigParser with the changed values
- cfgOptions = self.cfg.options(section)
- for name,value in self.iteritems():
- option = self.optionobj(name)
- if always is None or name in always or option.default != value or name in cfgOptions :
- self.cfg.set(section,name, option.tostring(value))
- # write the updated ConfigParser to the fileobj.
- self.cfg.write(fileobj)
-
- def getConfigOption(self, option, default=None):
- warnings.warn('getConfigOption() will go away in a future version of Yum.\n'
- 'Please access option values as attributes or using getattr().',
- DeprecationWarning)
- if hasattr(self, option):
- return getattr(self, option)
- return default
-
- def setConfigOption(self, option, value):
- warnings.warn('setConfigOption() will go away in a future version of Yum.\n'
- 'Please set option values as attributes or using setattr().',
- DeprecationWarning)
- if hasattr(self, option):
- setattr(self, option, value)
- else:
- raise ConfigError, 'No such option %s' % option
-
-
-def read_config(config_file, BaseConfigDerived):
- confparser = ConfigParser()
- opts = BaseConfigDerived()
- if os.path.exists(config_file):
- try:
- confparser.read(config_file)
- except ParsingError, e:
- print >> sys.stderr, "Error reading config file: %s" % e
- sys.exit(1)
- opts.populate(confparser, 'main')
- return opts
diff --git a/func/minion/utils.py b/func/minion/utils.py
deleted file mode 100755
index e8d1b39..0000000
--- a/func/minion/utils.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-Copyright 2007, Red Hat, Inc
-see AUTHORS
-
-This software may be freely redistributed under the terms of the GNU
-general public license.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-"""
-
-import os
-import socket
-import string
-import sys
-import time
-import traceback
-import xmlrpclib
-import glob
-
-import codes
-from func import certs
-from func.config import read_config
-from certmaster.commonconfig import MinionConfig
-from func import logger
-
-# "localhost" is a lame hostname to use for a key, so try to get
-# a more meaningful hostname. We do this by connecting to the certmaster
-# and seeing what interface/ip it uses to make that connection, and looking
-# up the hostname for that.
-def get_hostname():
-
- # FIXME: this code ignores http proxies (which granted, we don't
- # support elsewhere either. It also hardcodes the port number
- # for the certmaster for now
- hostname = None
- hostname = socket.gethostname()
- try:
- ip = socket.gethostbyname(hostname)
- except:
- return hostname
- if ip != "127.0.0.1":
- return hostname
-
-
- config_file = '/etc/certmaster/minion.conf'
- minion_config = read_config(config_file, MinionConfig)
-
- server = minion_config.certmaster
- port = 51235
-
- try:
- s = socket.socket()
- s.settimeout(5)
- s.connect((server, port))
- (intf, port) = s.getsockname()
- hostname = socket.gethostbyaddr(intf)[0]
- s.close()
- except:
- s.close()
- raise
-
- return hostname
-
-
-
-# this is kind of handy, so keep it around for now
-# but we really need to fix out server side logging and error
-# reporting so we don't need it
-def trace_me():
- x = traceback.extract_stack()
- bar = string.join(traceback.format_list(x))
- return bar
-
-
-def daemonize(pidfile=None):
- """
- Daemonize this process with the UNIX double-fork trick.
- Writes the new PID to the provided file name if not None.
- """
-
- print pidfile
- pid = os.fork()
- if pid > 0:
- sys.exit(0)
- os.setsid()
- os.umask(0)
- pid = os.fork()
-
-
- if pid > 0:
- if pidfile is not None:
- open(pidfile, "w").write(str(pid))
- sys.exit(0)