# Authors: # Andrew Wnuk # Jason Gerard DeRose # # Copyright (C) 2009 Red Hat # see file 'COPYING' for use and warranty information # # 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; version 2 only # # 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 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 """ Backend plugin for IPA-RA. The `ra` plugin provides access to the CA to issue, retrieve, and revoke certificates via the following methods: * `ra.check_request_status()` - check certificate request status. * `ra.get_certificate()` - retrieve an existing certificate. * `ra.request_certificate()` - request a new certificate. * `ra.revoke_certificate()` - revoke a certificate. * `ra.take_certificate_off_hold()` - take a certificate off hold. """ from ipalib import api, SkipPluginModule if api.env.enable_ra is not True: # In this case, abort loading this plugin module... raise SkipPluginModule(reason='env.enable_ra is not True') import os, stat, subprocess import array import errno import binascii from httplib import HTTPConnection from urllib import urlencode, quote from socket import gethostname import socket from ipalib import Backend from ipalib.errors2 import NetworkError from ipaserver import servercore from ipaserver import ipaldap from ipalib.constants import TYPE_ERROR class ra(Backend): """ Request Authority backend plugin. """ def __init__(self): self.sec_dir = api.env.dot_ipa + os.sep + 'alias' self.pwd_file = self.sec_dir + os.sep + '.pwd' self.noise_file = self.sec_dir + os.sep + '.noise' self.ipa_key_size = "2048" self.ipa_certificate_nickname = "ipaCert" self.ca_certificate_nickname = "caCert" super(ra, self).__init__() def configure(self): if not os.path.isdir(self.sec_dir): os.mkdir(self.sec_dir) self.__create_pwd_file() self.__create_nss_db() self.__import_ca_chain() self.__request_ipa_certificate(self.__generate_ipa_request()) def _request(self, url, **kw): """ Perform an HTTP request. :param url: The URL to post to. :param kw: Keyword arguments to encode into POST body. """ uri = 'http://%s:%s%s' % (self.env.ca_host, self.env.ca_port, url) post = urlencode(kw) self.info('request %r', uri) self.debug('request post %r', post) conn = HTTPConnection(self.env.ca_host, self.env.ca_port) try: conn.request('POST', url, body=post, headers={'Content-type': 'application/x-www-form-urlencoded'}, ) except socket.error, e: raise NetworkError(uri=uri, error=e.args[1]) response = conn.getresponse() (status, reason) = (response.status, response.reason) data = response.read() conn.close() self.debug('request status %r', status) self.debug('request reason %s', reason) self.debug('request data %s', data) return (status, reason, data) def _sslget(self, url, **kw): """ Perform an HTTPS request using the ``sslget`` command. :param url: The URL to post to. :param kw: Keyword arguments to encode into POST body. """ uri = 'https://%s:%d%s' % (self.env.ca_host, self.env.ca_ssl_port, url) post = urlencode(kw) self.info('sslget %r', uri) self.debug('sslget post %r', post) argv = [ '/usr/bin/sslget', '-n', self.ipa_certificate_nickname, # nickname '-w', self.pwd_file, # pwfile '-d', self.sec_dir, # dbdir '-e', post, # post '-r', url, # url '%s:%d' % (self.env.ca_host, self.env.ca_ssl_port), ] (returncode, stdout, stderr) = self.__run(argv) self.debug('sslget returncode %r', returncode) self.debug('sslget stderr %s', stderr) self.debug('sslget stdout %s', stdout) return (returncode, stdout, stderr) def check_request_status(self, request_id): """ Check status of a certificate signing request. :param request_id: request ID """ self.debug('%s.check_request_status()', self.fullname) (s, r, data) = self._request('/ca/ee/ca/checkRequest', requestId=request_id, xmlOutput='true', ) response = {'status': '2'} if data is not None: request_status = self.__find_substring( data, 'header.status = "', '"' ) if request_status is not None: response['status'] = '0' response['request_status'] = request_status serial_number = self.__find_substring( data, 'record.serialNumber="', '"' ) if serial_number is not None: # This was "0x"+serial_number, but we should return it in # the same form used as arg to get_certificate(), etc. response['serial_number'] = serial_number request_id = self.__find_substring( data, 'header.requestId = "', '"' ) if request_id is not None: response['request_id'] = request_id error = self.__find_substring( data, 'fixed.unexpectedError = "', '"' ) if error is not None: response['error'] = error return response def get_certificate(self, serial_number=None): """ Retrieve an existing certificate. :param serial_number: certificate serial number """ self.debug('%s.get_certificate()', self.fullname) issued_certificate = None (returncode, stdout, stderr) = self._sslget( '/ca/agent/ca/displayBySerial', serialNumber=serial_number, xmlOutput='true', ) response = {} if (returncode == 0): issued_certificate = self.__find_substring( stdout, 'header.certChainBase64 = "', '"' ) if issued_certificate is not None: response['status'] = '0' issued_certificate = issued_certificate.replace('\\r', '') issued_certificate = issued_certificate.replace('\\n', '') self.debug('IPA-RA: issued_certificate: %s', issued_certificate) response['certificate'] = issued_certificate else: response['status'] = '1' revocation_reason = self.__find_substring( stdout, 'header.revocationReason = ', ';' ) if revocation_reason is not None: response['revocation_reason'] = revocation_reason else: response['status'] = str(-returncode) return response def request_certificate(self, csr, request_type='pkcs10'): """ Submit certificate signing request. :param csr: The certificate signing request. :param request_type: The request type (defaults to ``'pkcs10'``). """ self.debug('%s.request_certificate()', self.fullname) certificate = None (returncode, stdout, stderr) = self._sslget('/ca/ee/ca/profileSubmit', profileId='caRAserverCert', cert_request_type=request_type, cert_request=csr, xmlOutput='true', ) response = {} if (returncode == 0): status = self.__find_substring(stdout, "", "") if status is not None: response["status"] = status request_id = self.__find_substring(stdout, "", "") if request_id is not None: response["request_id"] = request_id serial_number = self.__find_substring(stdout, "", "") if serial_number is not None: response["serial_number"] = ("0x%s" % serial_number) subject = self.__find_substring(stdout, "", "") if subject is not None: response["subject"] = subject certificate = self.__find_substring(stdout, "", "") if certificate is not None: response["certificate"] = certificate if response.has_key("status") is False: response["status"] = "2" else: response["status"] = str(-returncode) return response def revoke_certificate(self, serial_number, revocation_reason=0): """ Revoke a certificate. The integer ``revocation_reason`` code must have one of these values: * ``0`` - unspecified * ``1`` - keyCompromise * ``2`` - cACompromise * ``3`` - affiliationChanged * ``4`` - superseded * ``5`` - cessationOfOperation * ``6`` - certificateHold * ``8`` - removeFromCRL * ``9`` - privilegeWithdrawn * ``10`` - aACompromise Note that reason code ``7`` is not used. See RFC 5280 for more details: http://www.ietf.org/rfc/rfc5280.txt :param serial_number: Certificate serial number. :param revocation_reason: Integer code of revocation reason. """ self.debug('%s.revoke_certificate()', self.fullname) if type(revocation_reason) is not int: raise TYPE_ERROR('revocation_reason', int, revocation_reason, type(revocation_reason) ) response = {} (returncode, stdout, stderr) = self._sslget('/ca/agent/ca/doRevoke', op='revoke', revocationReason=revocation_reason, revokeAll='(certRecordId=%s)' % serial_number, totalRecordCount=1, ) if returncode == 0: response['status'] = '0' if (stdout.find('revoked = "yes"') > -1): response['revoked'] = True else: response['revoked'] = False else: response['status'] = str(-returncode) return response def take_certificate_off_hold(self, serial_number): """ Take revoked certificate off hold. :param serial_number: Certificate serial number. """ response = {} self.debug('%s.take_certificate_off_hold()', self.fullname) (returncode, stdout, stderr) = self._sslget('/ca/agent/ca/doUnrevoke', serialNumber=serial_number, ) if (returncode == 0): if (stdout.find('unrevoked = "yes"') > -1): response['taken_off_hold'] = True else: response['taken_off_hold'] = False else: response['status'] = str(-returncode) return response def __find_substring(self, str, str1, str2): sub_str = None k0 = len(str) k1 = str.find(str1) k2 = len(str1) if (k0 > 0 and k1 > -1 and k2 > 0 and k0 > k1 + k2): sub_str = str[k1+k2:] k3 = len(sub_str) k4 = sub_str.find(str2) if (k3 > 0 and k4 > -1 and k3 > k4): sub_str = sub_str[:k4] return sub_str def __generate_ipa_request(self): certificate_request = None if not os.path.isfile(self.noise_file): self.__create_noise_file() returncode, stdout, stderr = self.__run_certutil(["-R", "-k", "rsa", "-g", self.ipa_key_size, "-s", "CN=IPA-Subsystem-Certificate,OU=pki-ipa,O=UsersysRedhat-Domain", "-z", self.noise_file, "-a"]) if os.path.isfile(self.noise_file): os.unlink(self.noise_file) if (returncode == 0): self.info("IPA-RA: IPA certificate request generated") certificate_request = self.__find_substring(stdout, "-----BEGIN NEW CERTIFICATE REQUEST-----", "-----END NEW CERTIFICATE REQUEST-----") if certificate_request is not None: self.debug("certificate_request=%s" % certificate_request) else: self.warning("IPA-RA: Error parsing certificate request." % returncode) else: self.warning("IPA-RA: Error (%d) generating IPA certificate request." % returncode) return certificate_request def __request_ipa_certificate(self, certificate_request=None): ipa_certificate = None if certificate_request is not None: response = self.request('profileSubmit', profileId='caServerCert', cert_request_type='pkcs10', requestor_name='freeIPA', cert_request=self.__generate_ipa_request(), xmlOutput='true', ) self.debug("IPA-RA: response.status: %d response.reason: '%s'" % (response.status, response.reason)) data = response.read() self.info("IPA-RA: IPA certificate request submitted to CA: %s" % data) return ipa_certificate def __get_ca_chain(self): response = self.request('getCertChain') self.debug('response.status: %r', response.status) self.debug('response.reason: %r', response.reason) data = response.read() certificate_chain = self.__find_substring(data, "", "") if certificate_chain is None: self.warning('IPA-RA: Error parsing certificate chain') else: self.info('IPA-RA: CA chain obtained from CA: %s', certificate_chain) return certificate_chain def __import_ca_chain(self): (returncode, stdout, stderr) = self.__run_certutil( [ '-A', '-t', 'CT,C,C', '-n', self.ca_certificate_nickname, '-a', ], stdin=self.__get_ca_chain(), ) if (returncode == 0): self.info("IPA-RA: CA chain imported to IPA's NSS DB") else: self.error("IPA-RA: Error (%d) importing CA chain to IPA's NSS DB", returncode) def __create_noise_file(self): noise = array.array('B', os.urandom(128)) f = open(self.noise_file, "wb") noise.tofile(f) f.close() def __create_pwd_file(self): hex_str = binascii.hexlify(os.urandom(10)) print "urandom: %s" % hex_str f = os.open(self.pwd_file, os.O_CREAT | os.O_RDWR) os.write(f, hex_str) os.close(f) def __create_nss_db(self): returncode, stdout, stderr = self.__run_certutil(["-N"]) if (returncode == 0): self.info("IPA-RA: NSS DB created") else: self.warning("IPA-RA: Error (%d) creating NSS DB." % returncode) """ sslget and certutil utilities are used only till Python-NSS completion. """ def __run_certutil(self, args, stdin=None): new_args = ["/usr/bin/certutil", "-d", self.sec_dir, "-f", self.pwd_file] new_args = new_args + args return self.__run(new_args, stdin) def __run(self, args, stdin=None): if stdin: p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout,stderr = p.communicate(stdin) else: p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout,stderr = p.communicate() self.debug("IPA-RA: returncode: %d args: '%s'" % (p.returncode, ' '.join(args))) # self.debug("IPA-RA: stdout: '%s'" % stdout) # self.debug("IPA-RA: stderr: '%s'" % stderr) return (p.returncode, stdout, stderr) api.register(ra) f='#n396'>396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
Cobbler CHANGELOG

- TBD 2009 - for 2.0 release
- Development release start
- (FEAT) add two new default flags to yum reposync (-m and -d) for grabbing comps automatically and also deleting duplicate RPMs
- (BUGF) validate gateway input against python-netaddr
- (FEAT) --kopts="~foo" --in-place can be used to delete a hash entry without affecting the others, not to be confused with "!foo" to supress it.
- (FEAT) web app moves to Django
- (FEAT) koan: Support for virt-autoboot feature (Xen only at this point, needs fixing)
- (FEAT) koan: use private address range for random MACs
- (FEAT) yum createrepo flags are now tweakable in settings
- (FEAT) new snippet for RHN Hosted: keep RHN keys between reinstalls
- (FEAT) allow per_distro snippets in addition to per_profile/per_system
- (BUGF) don't add port number to http_server if it's 80.
- (FEAT) support F11 fence-agent paths
- (BUGF) koan autodetection now can gather MACs/IPs for bridged interfaces better
- (FEAT) F11 and RAID support for keep_ssh_host_keys 
- (FEAT) keep_ssh_host_keys gets F11+RAID support
- (FEAT) per-task logging
- (BUGF) validateks checkes /every/ kickstart, as different variables may be present
- (FEAT) CLI now speaks XMLRPC (faster)
- (FEAT) task engine for webapp
- (FEAT) background APIs for all actions
- (FEAT) look at ksdevice when building buildiso CDs to add the proper network lines
- (BUGF) don't use RPM to check os_version, so RPM won't be called in rpm %post
- (BUGF) deprecated omapi/omshell features for manage_isc now removed
- (FEAT) removed configuration files for binary paths, will look for in PATH
- (FEAT) removed configuration settings indicating where some config files are
- (FEAT) yum priorities plugin setting for distro repos now tweakable in settings
- (BUGF) unfinished contrib. debian import/repo support disabled until it can be finished
- (FEAT) replicate is now greatly improved and smarter
- (BUGF) aclengine (unfinished feature) removed, (not the same as aclsetup)

- - 1.6.9
- (FEAT/cobbler) cobbler can now pass the virtio26 os version to virtinst, so virtio drivers can be used for RHEL5
.3 for instance
- (BUGF/cobbler) The URL to the WebUI documentation in the manpage was corrected
- (BUGF/cobbler) add the --nameserver option for static interfaces when defined (snippet fix)

- 1.6.7
- (BUGF/koan) Workaround for a bug in ybin, use --verbose for happy return codes
- (BUGF/cobbler) patch to redhat_register for Satellite 

1.6.6 (for more accurate listing, see release16 branch)
- (BUGF) don't use -m option for drac unless power_id is set
- (BUGF) don't run createrepo on reposync'd repos, it is redundant
- (BUGF) fix error message when wrong virt ram value is applied
- (FEAT) koan now partially works in source code form on EL 2
- (FEAT) discover repomd filenames (for F11 and later)
- (BUGF) Satellite also has a python module named "server" so we have to remove ours for Python imports.  This code was not used anyway.
- (BUGF) fix typo in network config snippet

- ... - 1.6.5
- (BUGF) don't use json on python x<=2.3 since we know it's simplejson x<2.0, which has unicode issues
- (FEAT) support F-11 imports
- (BUGF) don't add koan virtual interfaces for vlan tagged interfaces
- (BUGF) pair PAE and non-PAE content in imports better 
- (BUGF) don't try to scp /etc/cobbler/*.ks on replicate, this is an old path
- (BUGF) set proper umask on .mtime files
- (BUGF) fix koan error with unspecified arch using --kexec
- (BUGF) don't use --onboot=on in network config for kickstart for RHEL 3.
- (FEAT) koan can be built on EL-2

- Fri May 8 2009 - 1.6.4
- (BUGF) empty nameserver search paths now don't screw up resolv.conf
- (BUGF) unicode fix for --template-files feature
- (BUGF) mod python input fix for repo/profile associations in webapp
- (BUGF) change "hostname" to "option hostname" in dhcp.template
- (BUGF) fixes for unicode problem with Cheetah, repos, and json
- (BUGF) unicode fix for --template-files feature
- (BUGF) another unicode fix
- (BUGF) bonding interface setup for RHEL4 now works
- (BUGF) generate DHCP info even if netboot is disabled
- (BUGF) Change to network_config snippet to ignore bond masters to prevent anaconda failures when MAC addresses are not specified
- (BUGF) fix to CLI rename deleting subobjects via cobblerd (important!)
- (BUGF) fix blender cache problem with using dnsnames instead of record names (ISC DHCP management)
- (BUGF) quote host name in stock ISC template

- XXX - 1.6.3
- (BUGF) import with datestamp 0 when .discinfo is not found, do not crash
- (BUGF) various fixes to "cobbler report" when using non-standard formats
- (BUGF) rename with same name does not delete
- (BUGF) Fix for traceback when generating DHCP config and the bonding_master interface does not exist.
- (BUGF) remove trailing newline from tokens
- (BUGF) fix unicode handling of some fields under EL4
- (BUGF) fix webui search error (fixed better on devel)
- (BUGF) fix duplicate power reference
- (BUGF) fix error message that makes it appear dnsmasq had a problem restarting, when it did not
- (BUGF) spec requires python-urlgrabber
- (BUGF) change settings default from 'ksdevice=eth0' to 'bootif'
- (BUGF) keep DHCP restart quiet
- (BUGF) better hostname setting with DHCP management on
- (BUGF) fix bug in repo breed auto-detection code
- (BUGF) close file descriptors by using subprocess, not os.system
- (BUGF) make cobbler package Arch for now, require syslinux where it makes sense only.  To be changed in later release to download it from intertubes.

- Mon Mar 30 2009 - 1.6.2
- (BUGF) Fix for cache cleanup problem in cobblerd 

- Fri Mar 27 2009 - 1.6.1
- (FEAT) Improved anaconda monitoring code
- (FEAT) download comps.xml always (even if yum does not have the option)
- (FEAT) performance upgrades for cobblerd service to avoid reloads
- (FEAT) more code for s390 imports (WIP)
- (BUGF) import works better with rawhide
- (FEAT) snippet to preserve SSH host keys across reinstalls
- (FEAT) email trigger to notify when builds finish
- (FEAT) triggers now are written in Python, old system still exists.
- (FEAT) s390x zpxe support
- (BUGF) retry power 5 times before giving up
- (BUGF) fix for RHEL3 ppc imports
- (FEAT) use nameserver variable in network config in Anaconda when set
- (BUGF) sleep 5 seconds between power cycling systems
- (FEAT) support for /usr/bin/cobbler-register
- (FEAT) web UI search feature
- (FEAT) very simple "cobbler hardlink" command to optimize space in /var/www/cobbler
- (FEAT) new "change" trigger that runs on all adds/edits/removes/syncs
- (FEAT) an SCM trigger that knows about /var/lib/cobbler kickstarts, snippets, and config directories, and audits them for changes
- (BUGF) update ctime on object copies
- (BUGF) fix cobbler check code that makes sure default password is not in use
- (BUGF) remove duplicate text box for management classes from server edit page
- (BUGF) fix stderr output on Ctrl+C
- (BUGF) potential performance savings WRT duplicate python objects
- (BUGF) don't deserialize during sync, it makes it take twice as long
- (FEAT) Ubuntu support for import (added/improved)
- (BUGF) make DHCP managemnet work with bonding
- (BUGF) teach serializer_catalog to fly with JSON
- (BUGF) don't use yumdownloader when rpm_list is []
- (BUGF) fix default kickstart location
- (BUGF) properly "flatten" environment values for webapp
- (BUGF) fix for MSIE rendering in web app
- (BUGF) stop yumdownloader including system yum repos
- (DOCS) update webui project page link
- (BUGF) remove caching logic from remote.py
- (FEAT) added --exclude-dns option to buildiso
- (BUGF) fix string comparisons to tolerate unicode
- (BUGF) fix dealing with name servers and name servers search, esp in web app

- Tue Mar 3 2009 - 1.4.3
- (BUGF) fix OMAPI support's (note: deprecated) usage of subprocess
- (BUGF) don't traceback on invalid cmd ("cobbler distro list --name=foo")
- (BUGF) fix import usage with --kickstart option (no more traceback)
- (BUGF) fix removal of images with child system objects
- (BUGF) make --rpmlist on repo use same parsing routes as the rest of cobbler
- (BUGF) default value for server override should be <<inherit>> not <inherit>
- (BUGF) ensure if virt bridge is set to "" it will apply the value from settings
- (BUGF) cobbler check should say path to config file is /etc/cobbler, not /var/lib
- (FEAT) enable cobblerweb username/pass logins when authing with spacewalk
- (BUGF) allow --kopts to take parameters that are shell quoted.
- (BUGF) allow kernel options to start with '-'
- (BUGF) Use shlex for parsing --kopts to allow a wider variety of kernel options
- (BUGF) prevent potential traceback when --template-file data isn't a hash
- (BUGF) anaconda doesn't honor nameserver always, set manually
- (BUGF) various post install network snippet fixes
- (BUGF) fix OMAPI support's (note: deprecated) usage of subprocess
- (SPEC) fix build for rawhide now that yaboot is included
- (BUGF) allow src and noarch arches for repo objects
- (BUGF) move to PyYAML for YAML implementation since it is better maintained
- (BUGF) fixed web-interface editing of ownership
- (BUGF) fixed web-interface editing of management classes
- (BUGF) don't run full sync in import, sync makes the install system unavailable for very short periods of time
- (FEAT) XMLRPC functions for searching objects, just like the Python API has
- (BUGF) make "find repo" CLI command search repos, not systems

- XXX - 1.4.2
- (BUGF) fix WTI power templates
- (FEAT) add WTI power type
- (BUGF) remove Python 2.6/3000 warnings
- (BUGF) fix typo in network template (DNS enumeration)
- (BUGF) make buildiso work for systems that are using bonding
- (BUGF) blending fix for --template-files
- (BUGF) cobbler check ignores comments in TFTP config
- (BUGF) fix image type field editing in the webapp
- (BUGF) allow deletion of eth0 if other interfaces are present
- (BUGF) fix server-override setting in CLI for profile objects
- (BUGF) systems and profiles are now sorted for "cobbler buildiso"
- (BUGF) ensure that directories exist when installing a template file
- (BUGF) fix for typo in network config snippet
- (BUGF) fix for func integration script (should overwrite config, not append)
- (BUGF) append nameservers and gateway, if set, for buildiso 

- Fri Jan 09 2009 - 1.4.1
- (BUGF) Cobbler check looks for right httpd on SUSE
- (BUGF) post_install_network_config snippet had bash errors
- (BUGF) don't run restorecon programatically
- (FEAT) have cobbler check mention when semanage rules should be applied
- (BUGF) fix an obscure xmlrpclib corner case where a string that looks like an int can't be served because xmlrpclib thinks it's an int.  Applies to XMLRPC consumers only, not CobblerWeb or the cobbler CLI.
- (BUGF) fix external kickstart URLs (not templated) and per-system overrides.
- (BUGF) fix 'cobbler check' code for SuSE services
- (FEAT) batch editing on the system page.

- Fri Dec 19 2008 - 1.4
- (----) Stable release of 1.3 development branch

- Fri Dec 19 2008 - 1.3
- (FEAT) ACLs to extend authz (see Wiki)
- (FEAT) puppet integration with --mgmt-classes and external nodes URL
- (FEAT) added puppet external nodes script, cobbler-ext-nodes
         see https://fedorahosted.org/cobbler/wiki/UsingCobblerWithConfigManagementSystem
- (FEAT) ability to use --enable-menu=0/1 to hide profiles from the PXE menu, and config setting to change default value for --enable-menu
- (FEAT) added livecd based physical machine cloner script to "contrib"
- (FEAT) enable import for debian ISOs and mirrors (1 distro at a time for now)
- (FEAT) auto-create rescue profile objects
- (FEAT) included network_config snippet and added --static=0/1 to system objects
- (FEAT) cobbler report gains additional options for Wiki formatting, csv, and showing only certain fields
- (FEAT) changed default kernel options to include ksdevice=bootif (not ksdevice=eth0) and added ipappend 2 to PXE
- (FEAT) distro edits now no longer require a sync to rebuild the PXE menu
- (BUGF) minor tweak to the blender function to remove a certain class of typing errors where a string is being blended with a list, should not have any noticable effect on existing installs
- (BUGF) add missing import of "_" in remote.py
- (FEAT) upgraded webui editing for multiple NICs
- (FEAT) "template_universe" variable created for snake's usage, variable contains all template variables and is also passed to the template.
- (FEAT) refactored import with better Debian/Ubuntu support
- (FEAT) Func integration snippets and new settings
- (FEAT) settings file and modules.conf now generated by setup.py using templates
- (FEAT) --template-files makes cobbler more of a full config management system!
- (FEAT) cobbler reposync now supports --tries=N and --no-fail
- (FEAT) duplicate hostname prevention, on by default
- (FEAT) make import work for Scientific Linux
- (FEAT) distro remove will remove mirrored content when it's safe to do so
- (FEAT) repo remove will remove mirrored repo content
- (FEAT) added snippet for better post-install network configuration
- (BUGF) duplicate repo supression to prevent errors in certain Andaconda's
- (FEAT) post_network_snippet/interfaces can set up VLANs
- (FEAT) call unittests with nose, which offers cleaner output, see tests/README
- (FEAT) update included elilo to 3.8
- (BUGF) quote append line for elilo
- (BUGF) added ExcludeArch: ppc64
- (FEAT) --environment parameter added to reposync
- (BUGF) have triggers ignore dotfiles so directories can be version controlled (and so on)
- (FEAT) init scripts and specfiles now install on SuSE
- (TEST) added remote tests, moved existing unit tests to api.py methods 
- (FEAT) import can auto assign kickstarts based on distro (feature for beaker)
- (FEAT) import now saves the dot version of the OS in the comment field
- (FEAT) import now adds tree build time
- (FEAT) --comment field added to all objects
- (FEAT) keep creation and modification times with each object
- (FEAT) added ppc imports and arches to supplement s390x (and assoc koan chage)
- (FEAT) added number of interfaces required to each image
- ~~~ 1.3.2
- (BUGF) fix for possible import of insecure modules by Cheetah in Cobbler web.
- (FEAT) new version function
- (FEAT) misc WUI organization
- (FEAT) allow auth against multiple LDAP servers
- (FEAT) replicate now copies image objects
- (BUGF) replicate now uses higher level API methods to avoid some profile sync errors when distros fail
- (FEAT) /etc/cobbler/pxe and /etc/cobbler/power are new config file paths
- (FEAT) /var/lib/cobbler/kickstarts is the new home for kicktart files
- (FEAT) webui sidebar reorg
- (FEAT) manage_dhcpd feature (ISC) now checks service status before restarting
- (BUGF) omapi for manage_dhcp feature (ISC) now defaults to off
- (FEAT) added module whitelist to settings file
- (BUGF) don't let the service handler connect to itself over mod_python/proxy, RH 5.3 does not like
- (FEAT) mtimes and ctimes and uids in the API
- (FEAT) new functions to get objects based on last modified time, for sync with other apps
- ~~~ 1.3.3 Test release
- (FEAT) Python 2.6 specfile changes
- ~~~ 1.3.X
- (FEAT) cobbler check output is always logged to /var/log/cobbler/check.log
- (FEAT) new redhat_register snippet and --redhat-management-key options!
- (BUGF) SELinux optimizations to symlink/hardlink/chcon/restorecon behavior
- (----) no SELinux support on EL 4
- (FEAT) yum_post_install_mirror now on by default

- ??? - 1.2.9
- (BUGF) do not allow unsafe Cheetah imports

- Wed Oct 15 2008 - 1.2.8
- (BUGF) make cobbler read /etc/cobbler/settings.py (introduced in 1.2.6)

- Tue Oct 14 2008 - 1.2.7
- (BUGF) go easier on restrictings when importing subprofiles to prevent load errors
- (FEAT) added debuginator script to scripts/ (not shipped with RPM)

- Fri Oct 10 2008 - 1.2.6
- (BUGF) fix image vs system parentage problem affecting cobbler replicate
- (BUGF) fix restart-services trigger to not restart dns unneccessarily
- (BUGF) add missing variable newname to signature for remote copy_ functions
- (BUGF) fix for ownership ownership module when editing kickstarts

- Fri Sep 26 2008 - 1.2.5
- (BUGF) expose --arch for "cobbler image add"
- (BUGF) unbreak dnsmasq DHCP management, similar to ISC bug
- (BUGF) fix --arch for cobbler distro add/edit
- (BUGF) fix merge error with remote.py's remove_profile function (fix webapp)
- (BUGF) make keep_updated and mirror_locally checkboxes in WebUI display correctly

- Mon Sep 08 2008 - 1.2.4
- (BUGF) simple rebuild to remove cli_report.py, which is not in git

- Sun Sep 07 2008 - 1.2.3
- (BUGF) fix to manage_isc.py code

- Fri Sep 05 2008 - 1.2.2
- (BUGF) fix to where elilo location is loaded in manage_isc.py
- (BUGF) populate netboot_enabled in WebUI correctly
- (BUGF) make RPM own some unowned directories in "triggers"
- (BUGF) add named_conf setting to settings

- Tue Sep 02 2008 - 1.2.1
- (BUGF) fix merge problem with 1.2 

- Fri Aug 29 2008 - 1.2.0
- (FEAT) All development work from 1.X merged in
- (FEAT) when --netboot-enabled is toggled, rather than deleting the PXE config, create a local boot PXE config
- (BUGF) disable some s390 aspects of cobbler check until it is supported
- (FEAT) new --os-version, better validation for --breed, --breed/--os-version also for images

- ??? - 1.1.1
- (FEAT) make template replacement use regex module
- (BUGF) remove bootloader check in settings as that code doesn't need it
- (BUGF) refinements to image handling
- (FEAT) getks command added to command line
- (BUGF) don't print traceback during certain SystemExits
- (BUGF) --help now works more intuitively on odd command line usage
- (BUGF) use pxesystem for systems, not pxeprofile
- (FEAT) make Cheetah formatting errors contain help text for users
- (FEAT) --kopts-post can configure post-install kernel options
- (BUGF) subtemplates are now errorCatcher Echo compatible

- ??? - 1.1.0
- devel branch
- added cobbler aclsetup command for running cobbler as non-root
- added cobbler find command to do searches from the command line
- fix mkdir invocation
- improved cobbler replicate, it now can rsync needed files
- further templatize ISC dhcp config file (pay attention to /etc/cobbler/dhcp.template.rpmnew !)
- fix for NFS imported URLs during kickstart generation
- added yumreposync_flags to settings, default "-l" for use plugins
- added an extra mkdir for rhn's reposync, though I believe the -l cures it already
- allow mod python bits to work via non-80 http ports
- when mirroring repos, act as 686 not 386 to get all the kernel updates
- upgrades to cobbler buildiso
- added patch to allow --in-place editing of ksmeta/kopts
- added patch to allow multiple duplicate kernel options
- fix kickstart serving when the tree is on NFS
- s390x import, added support for s390x "pseudo-PXE" trees
- added support for tracking image objects and virtual ISO images
- support for multiple copies of the same kernel option in kopts
- add cobbler bash completion script
- fix bug with 255 kernel options line warning not firing soon enough
- add findks.cgi support back as http://server/cblr/svc/op/findks
- merge patch to surface status over API
- make yum repos served up for /etc/yum.repos.d fully dynamic (mod_python)
- cobbler find API calls and command line usage can now use fnmatch (wildcards)
- return code cleanup (0/1 now more predictable)
- added comments to /etc/cobbler/modules.conf
- during import non-xen kernels will default --virt-type to qemu
- when editing/adding profiles, auto-rebuild the PXE menu
- added http://cobbler.example.org/cblr/svc/op/list/what/systems (or profiles, etc)
- in the webui, only show compatible repos when editing a profile
- refresh cobblerd cache before adding objects
- system object IP's ok in CIDR notation (AAA.BBB.CCC.DDD/EE) for defining PXE behavior.
- split partition select template into two parts (old one still ships)
- cleanup some stock kickstarts so we always use $kickstart_start
- hook ctrl+c during serializer writes to prevent possible corruption of data in /var/lib/cobbler
- added 'serializer_catalog' as the new default serializer.  It is backward compatible and much faster.
- removed serializer_shelve 
- webui page lookups don't load the full object collection
- systems can also inherit from images
- changes to PXE images directly
- bootloaders is no longer a config file setting
- we can now look for syslinux in one of two places (/usr/lib, /usr/share)
- cobbler hardlinks a bit more when it can for /var/www image copies
- add Xen FV and VMware virt types to WebUI

- Thu Jul 17 2008 - 1.0.4 (tentative)
- Backported findks.cgi to mod_python, minor mod_python svc handler changes

- Wed Jun 03 2008 - 1.0.3
- Fix typo in replicate code
- remove rhpl reference
- scrub references to manage_*_mode and rewrite the restart-services trigger
- add new settings to control whether the restart-trigger restarts things
- yum reposync should also pull i686 kernels, not just i386
- make cobblerd close file handles
- fix kickstart serving when the tree is on NFS
- fix missing reposync createdir (also now in stable branch)
- add back missing remove_profile/remove_repo
- remove profile_change support

- Mon Jun 09 2008 - 1.0.2
- Fix mkdir invocation
- Fix error message output from failed kickstart rendering
- manpage edits
- make buildiso work for SuSE

- Tue Jun 03 2008 - 1.0.1
- Fix misformatted warning in "check"
- Do not have RPM own tftpboot, just generate files in TFTP dir as detected
- Default arches to 'i386' not 'x86' for consistency, esp. in import
- When querying kickstart templates, do not return directories
- Make triggers for add/delete work for renames and copies (same triggers)
- Do not cache snippets so they can be tweaked w/o starting the service
- Make manpage reference /etc/cobbler/settings, not /var/lib
- Added manage_forward_zones/manage_reverse_zones to included config file
- Fix python double-use-of-parameter error

- Mon May 12 2008 - 0.9.2
- run createrepo with less preconditions during cobbler reposync
- doc upgrades and error handling for "cobbler replicate"
- improved error message that occurs when copying from nfs w/ rootsquash
- mac duplication checking improvements for CLI
- add warning to cobbler check if selinux is on and Apache boolean not set
- added warning to cobbler check if templates use the default password
- setting per-system kickstart template to "" or "delete" restores inheritance
- if repos in profiles no longer exist, remove noisy warning, move to "check"
- move warning about reposync to check also (check is more useful at runtime now)
- build pxe trees for systems even if interface0 is undefined
- add sync() back into XMLRPC API, missing in 0.9.1
- added 'distro_name', 'profile_name', and 'system_name' to generated template vars
- it's now possible to undefine a --ksmeta or kopts symbol defined in a parent with "!foo"
- log errors while rendering kickstarts
- comments added to the config file, neat!
- settings file is now /etc/cobbler/settings

- Fri May 09 2008 - 0.9.1
- patch to allow yumopts to override gpgcheck
- applied patch to send hostname from ISC
- added patch to allow --kopts/--ksmeta items to be cleared with --kopts=delete
- tftpboot location is now inferred from xinetd config (added for F9 compat)
- added authn_ldap and stub for authz_configfile
- authz_configfile allows filtering ldap/other users by config file
- WebUI now has checkbox on distro/profile for deleting child objects
- cli has different semantics between "add" and "edit" now for safety reasons
- cobbler wants to keep IPs/MACs unique now in configuration (can be disabled)
- added --clobber option to allow add to overwrite existing objects (for scripts)
- updated/tested kerberos support for those needing to auth against it 
- update menu.c32 to 3.62 to allow for timeouts during menu (and future submenu)
- update PXE defaults to invoke menu.c32 automatically w/ timeout
- removed dependency on rhpl
- import can now take an --arch (and is recommended usage)
- now possible to override snippets on a profile/system specific basis
- provide a different default sample kickstart for imports of F8 and later
- support for kerberos authentication
- revamped pre/post install triggers system (triggered via cgi from kickstart wget)
- logrotate should not send emails to root when restarting services
- default core (but not repo add) repos to priority 1 (lowest) if using priorities plugin
- change default authentication to deny_all, xmlrpc_rw_enabled now on by default
- additional fix for mod_python select box submissions
- set repo arch if found in the URL and no --arch is specified
- CGI scripts have been moved under mod_python for speed/consolidation
- kickstart templates are now evaluated dynamically
- optional MAC registration is now built-in to requesting kickstarts
- legacy static file generation from /var/www/cobbler removed
- implement "cobbler ___ dumpvars --name=X" feature to show template vars
- validateks now works against all URLs as opposed to rendered local files
- now possible to create new kickstarts in webui, and delete unused ones
- support for OMAPI for avoid dhcp restarts
- support for managing BIND
- xen kernel (PV) distros do not get added to PXE menus as they won't boot there
- cobbler buildiso command to build non live ISOs
- cobbler replicate command
- added cobbler repo option --mirror-locally to reference external repos without mirroring
- all virt parameters on profiles can now be overriden on cobbler profile objects
- added some additional links for kickstart viewing/editing to the web page

- ??? - 0.8.3
- Make createrepo get run for local cobbler reposync invocations as needed
- fix WebUI documentation URL
- fix bug in /etc/cobbler/modules.conf regarding pluggable authn/z
- fix default flags for yumdownloader
- fix for RHEL 4u6 DVD/tree import x86_64 arch detection
- fix for dnsmasq template file host config path
- fix dnsmasq template to point at the correct hosts file
- force all names to be alphanumeric
- all mod python pieces now happy with Unicode output

* Fri Feb 22 2008 - 0.8.2
- fix to webui to allow repos to be edited there on profile page
- disable local socket XMLRPC as nothing is using it.
- fixed findks.cgi so it supports multiple NICs
- import now supports both --path and --mirror as aliases, as before
- added change_profile.cgi for changing profiles from CGI
- added register_mac.cgi

* Wed Feb 20 2008 - 0.8.1
- bugfix in reposync code
- don't print tracebacks on SystemExit from optparse
- manpage tweaks

* Fri Feb 15 2008 - 0.8.0 (TBD)
- stable release of 0.7.* branch plus ...
- fixed potential user problem with source_repos in upgrade scenario
- additional higher level API functions for find, fixes for other higher level API functions
- better messaging when insufficient permissions on needed files
- update permissions on reposync fixes

* Thu Jan 31 2008 - 0.7.2 (0.8 rc)
- default_virt_file_size and default_virt_ram added to settings
- enforce permissions/selinux context after reposync
- better API for copying/renames, API consistancy cleanup
- support for renames that resolve dependencies, inclusion in CLI+webapp
- remove leading newline in rendered template files, which apparently breaks AutoYAST?
- recursive syncs automatically sync all subobjects when editing parent objects (default behavior)
- deletes can now be done recursively (optional --recursive on distro/profile remove)
- 'cobbler list' is now (re)sorted

* Wed Jan 09 2008 - 0.7.1
- allow imports to force usage of a specific kickstart template with --kickstart
- added --yumopts parameter to repos (works just like --kopts/--ksmeta)
- minor doc fixes
- fix for name of F8 comps.xml file
- added option --rsync-flags to import command
- added http_port to settings to run Apache on non-80
- rsync during createrepo now keeps filesystem permissions/groups
- ...

* Mon Dec 10 2007 - 0.7.0
- Testing branch
- Fix bug related to <<inherit>> and kickstart args 
- Make CLI functions modular and use optparse
- Quote wget args to avoid creating stray files on target system
- Support Xen FV as virt type (requires F8+)
- Implemented fully pluggable authn/authz system
- WebUI is now mod_python based
- Greatly enhanced logging (goes to /var/log/cobbler/cobbler.log)
- ...

* Wed Nov 14 2007 - 0.6.4
- Changed permissions of auth.conf
- Fixes for working with rhn_yum_plugin
- still allow repo configuration for distro repos that have just 1 repo (like C5.1)
- disable CGI weblogging by default (backend logging TBA)
- fix WebUI handling of keep_updated (repo field) and netboot_enabled (system field)
- disable the blender_cache as it's running afoul of the sync code
- update htaccess file to only authenticate the webui, not nopxe.cgi and findks.cgi

* Wed Nov 07 2007 - 0.6.3
- Be able to define and use Multiple NICs per system
- Add --virt-cpus to profile editing
- Fix bug where WUI (XMLRPC) auth wasn't supported on EL4
- Add --virt-bridge to profile editing and NICs
- Added serializer_shelve (as option) for added performance/persistance over YAML, experimental in /etc/cobbler/modules.conf, see Wiki
- Backup state files and migrate state structures upon RPM upgrade
- Added some more redundant files (for unsupported distros) to the rsync.exclude file
- added pre-sync and post-sync triggers, service restarts are now handled by /var/lib/cobbler/triggers
- webui now uses htaccess (see manpage and Wiki for setup instructions)
- added pagination to the WUI to keep pages from growing overly long
- added --server-override parameter for help with multi-subnet configurations (also see Wiki)
- removed yum-utils as a hard requirement, cobbler check now looks for yum-utils
- fixed bug where cobbler would try to copy hardlinks to themselves during sync
- misc random bugfixing

* Fri Sep 28 2007 - 0.6.2
- cobbler repo auto-add to discover yum repos automatically
- fix bug that allows empty mac addresses (None) in dhcpd.conf
- kickstarts automatically save kickstart file used to /root/cobbler.ks
- allow multiple (comma-seperated) values for --virt-size
- removed deprecated 'enchant' function (use SSH and koan instead)
- cleanup of a few unused settings
- allow for serialization modules to be selected in /etc/cobbler/modules.conf
- patch to allow for reposync of specific repos, even if not set to update
- added --dhcp-tag section for better DHCP customization (esp with multiple subnets)
- added Apache proxying around XMLRPC port for wider network access
- refactor XMLRPC API and establish a read-write API
- allow for configuring of read-write XMLRPC users in /etc/cobbler/auth.conf
- WebUI
- packaged /var/lib/cobbler/settings as a config file
- added BuildRequires to help build on other platforms
- relocate cgi-bin files to cgi-bin/cobbler for namespacing
- fix syslog logging for systems not in the cobbler DB.
- fix bug in which non-lowercase intermediate objects could be deleted 
 
* Thu Aug 30 2007 - 0.6.1
- re enable --resolve in yumdownloader (cobbler repo mgmt feature)
- fix get_distros_for_koan API function in cobblerd (not used by koan)
- allow find API to search by arbitrary fields
- status and logging now shows system names
- upgraded init scripts
- zeroconf/avahi publishing for cobblerd service
- logRequests = 0 for XMLRPC.  Make it be quiet.
- ignore subdirectories of /var/lib/cobbler/snippets
- fixed bug in graph rendering that allowed for upward property propogation in some cases
- fixed bug that did not correctly evaluate repository settings of inherited sub-profiles/objects
- tweaked domU sample kickstart to include wget
- added some more unit tests
- fix typo down one error path in cobbler sync.
- fix reposync handling when using rsync protocol and directory paths do not contain arch
- allow basic usage of Cheetah variables in config files @@server@@, etc.
- fix auto-repo attachment for distros with split trees (i.e. RHEL5)

* Thu Aug 09 2007 - 0.6.0 
- bugfix in error path in "cobbler check"
- stable release for 0.5.x

* Thu Jul 26 2007 - 0.5.2 (RC)
- Have cobbler check ensure services are started
- Add cobbler validateks command to look for broken rendered kickstarts
- Added -v/--version
- Added SNIPPET::foo capability to pull /var/lib/cobbler/snippets/foo into templates (anywhere)
- Import can now take an --available-as=nfs://server:/mount/point to do cobbler import without mirroring
- Feature to enable "pxe_just_once" for boot loop prevention

* Fri Jul 20 2007 - 0.5.1
- Added logging for cobblerd -- /var/log/cobbler/cobblerd.log
- Cobblerd now ignores XMLRPC IOError
- Added findks.cgi
- Misc bugfixing
- Added --virt-path, --virt-type

* Wed Jun 24 2007 - 0.5.0
- Remove hardcode of /var/www/cobbler in cobblerd
- Improve various warning warning messages
- cobbler (objecttype) (objectname) now gives info about the object instead of just all objects
- Added --hostname to "cobbler system add", --ip-address (or --ip) is also a better alias for the misnamed --pxe-address
- Optionally use dnsmasq for DHCP (and DNS!) instead of ISC dhcpd.
- Add --mac and remove requirement for --name to be an ip, mac, or hostname.
- Manpage cleanup
- Patch to allow pre and post triggers
- Patch to allow --createrepo-flags and to cache on import, fix multiple calls to createrepo
- Various modifications to allow for profile inheritance