Recent posts

Authenticate Trac Against phpBB

So, Chuck, over at Cobra wanted to get his trac site up and running and was wondering about using the exisiting accounts that people had in the phpBB3 forums. Trac being Python, and phpBB being, obviously, PHP, there was no stock way of accomplishing this.

First, Trac's authentication meme is basically: get someone else to do it. Generally speaking, this is the web server. That's all fine and dandy, but some people want a bit more. Thankfully, Matt Good wrote the Account Manager plugin. This neat little plugin lets you auth against the trac db, htpasswd files, htdigest files, etc. It also allows for easier management of accounts. The most wonderful thing about it, however, is the IPasswordStore interface it defines. This little beauty lets you auth against just about anything where the input is a username and password.

Well, amazingly, phpBB manages to authenticate users via a username and password. Graciously, Cobra sponsored me to write up an IPasswordStore implementation to use the existing phpBB database as the authentication store for the adjoining Cobra trac site. Hence the birth of PhpBbAuthPlugin. So, for all you phpBB junkies that need to run Trac sites, you now have an option where with you can keep your accounts one and the same.


Hey, phpBB guys, don't you think that 73 columns in your user table is a bit excessive?

15 Character Limit

Let's establish some facts.

  • MS SQL Server 2005 allows the sa password to be longer than 15 characters.
  • MS Windows XP allows a password longer than 15 characters.

Given these two facts, one would assume that Microsoft has a policy of allowing arbitrary length password (or at least really long ones). However, if one were to assume this, one would be wrong.

Microsoft's Business Solutions - Great Plains 8 does NOT allow passwords longer than 15 characters. I'll admit that GP8 is a bit out of date. It was released in 2003, I believe. But, really, was there a need to limit password lengths in 2003? I don't think so.

Once again, thank you Microsoft for such a wonderful piece of software. If anyone is considering Microsoft Dynamics:GP (as it is now called), save yourself the misery and check out HansaWorld or some other product instead.

DIAF

!PyCon 2008 - Here I Come!

PyCon 2008: Chicago

PyCon is March 14th through 16th with the 17th through 20th being open for sprints. PyCon was a blast last year, thanks to Financial Aid from the PSF. Thankfully, my employer is sending me this year. I'll be taking the SQLAlchemy tutorials along with Automating Windows Applications with win32com. I'm horribly excited!

So, you should all sign up and attend PyCon. It's a great time to geek out with lots of other Python developers. Come join the Trac sprint and have a good time. If you need a little assistance, shoot off an application to the PSF for Financial Aid. Hope to see you there.

Populating ''Assign To'' Drop Down in Trac

When configuring a Trac environment, you can set the following option:

[ticket]
restrict_owner = true

This will change the Assign To ticket filed into a select box that only contains existing users. However as it says on the TracTickets page, the user must have logged, in at least once, and set their email address.

If you run multiple Trac sites, and have a set of common users across all Trac sites, it gets annoying to have to log into each one and set the email.

So, what is one to do? Well, there are two things that need to be entered into the database: a session record, and an email record.

To enter a session record, we need to add a row to the session table. The schema for the session table looks like

         Table "session"
    Column     |  Type   | Modifiers
---------------+---------+-----------
 sid           | text    | not null
 authenticated | integer | not null
 last_visit    | integer |

The sid is the username, authenticated will simply be 1, and last_visit needs to be set to a date, expressed as seconds since the epoch.

For example:

INSERT INTO session (sid, authenticated, last_visit) VALUES ('pacopablo', 1, 1195926785);

Now, to set the actual email address. That will go in the session_attribute table.

The schema for the session_attribute table is as follows:

    Table "session_attribute"
    Column     |  Type   | Modifiers
---------------+---------+-----------
 sid           | text    | not null
 authenticated | integer | not null
 name          | text    | not null
 value         | text    |

Once again, sid is the username, authenticated will be 1, name refers to the type of attribute this is, email in this case, and value will be the actual email adress.

For example:

INSERT INTO session_attribute (sid, authenticated, name, value) VALUES ('pacopablo', 1, 'email', 'pacopablo@pacopablo.com');

There is also a name attribute that is used which can be set:

INSERT INTO session_attribute (sid, authenticated, name, value) VALUES ('pacopablo', 1, 'name', 'Pacopablo Parangaricutirimicuaro');

Of course, going into a SQL interface to do this isn't really any better than logging into the Trac site and setting it yourself. It's also more error prone.

Python to the rescue! We'll just whip up a simple little script that parses a command line, loads up the Trac environment, and creates the records for us. Behold:

from trac.env import Environment
from optparse import OptionParser
import sys
import os
def doArgs():
    """Parse command line options"""
    description = "%prog is used to seed the user's full name and email."
    parser = OptionParser(usage="usage: %prog [options] [username]",
                          version="1.0", description=description)
    parser.add_option("-e", "--env", dest="envpath", type="string",
                      help="Path to Trac environment", metavar="<path>",
                      default=".")
    parser.add_option("-m", "--email", dest="email", type="string",
                      help="Emal address", metavar="<email>", default=" ")
    parser.add_option("-f", "--fullname", dest="fullname", type="string",
                      help="Full Name", metavar="<name>", default=" ")
    (options, args) = parser.parse_args()
    if len(args) < 1:
        print "You must specify a username"
        sys.exit(1)
    options.user = args[0]
    if not os.path.exists(options.envpath):
        print "The path >%s< does not exist.  Please specify an existing path." % options.envpath
        sys.exit(1)
    options.args = args
    return options
if __name__ == '__main__':
    opts = doArgs()
    env = Environment(opts.envpath)
    cnx = env.get_db_cnx()
    cur = cnx.cursor()
    cur.execute("INSERT INTO session (sid, authenticated, last_visit) "
                "VALUES (%s, 1, 1195926785)", [opts.user])
    cur.execute("INSERT INTO session_attribute (sid, authenticated, name, "
                "value) VALUES (%s, 1, 'name', %s)",
                [opts.user, opts.fullname])
    cur.execute("INSERT INTO session_attribute (sid, authenticated, name, "
                "value) VALUES (%s, 1, 'email', %s)",
                [opts.user, opts.email])
    cnx.commit()
    cnx.close()
    sys.exit()

Most of the script is doing validation on input, and even then, it's not that much. So, save the script as trac_set_email.py, or some other such memorable name, fire it up1.

dev ~ # python trac_set_email.py -help
Usage: trac_set_email.py [options] [username]
trac_set_email.py is used to seed the user's full name and email.
Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -e <path>, --env=<path>
                        Path to Trac environment
  -m <email>, --email=<email>
                        Emal address
  -f <name>, --fullname=<name>
                        Full Name
dev ~ # python trac_set_email.py --env /srv/trac/env/dev/ --fullname "Test User" --email pacopablo@pacopablo.com testuser

And there you have it. Enjoy2


  1. 1. If you're crazy like me, and install Trac into a different location than the system site-packages directory, you'll need to specify the PYTHON_PATH environment variable. For example: PYTHONPATH="/var/trac-0.11dev/lib/python2.5/site-packages/" \ python trac_set_email.py --env /srv/trac/env/dev/ --fullname "Test User" --email pacopablo@pacopablo.com testuser
  2. 2. And here's to hoping that Trac 0.12 has a better user management interface so that we don't have to manually enter records into the database

htpasswd with Python

As many Apache users know, the htpasswd1 is used to create a file with username/password pairs. The format for the file is simply a username, colon, encrypted password. For example:

foo:oNAU4bgeqQHt2

The username is foo and the password is bar encrypted with a salt of oN2

Now, there are good reason why an admin might not want to install apache in order to get htpasswd, yet still need to create a password file. Since there isn't a good reason against having Python installed, we can simply use that to create the file.

The encryption used by htpasswd is the basic UNIX crypt(3) function. Python provides a very nice interface to this function3.

import crypt
print crypt.crypt('bar', 'oN')

This will print bar, encrypted with a salt of oN4

Obviously, the above code isn't incredibly complex. So below is a bit of code that might be a little more useful.

# Script should be passed two paramters
# username and password
import crypt
import sys
if len(sys.argv) == 3:
    print("%s:%s" % (sys.argv[1], crypt.crypt(sys.argv[2], sys.argv[2])))

To use the code, save it as htpasswd.py or something and then simply pass it two parameters, username then password, and redirect the output into a file. For example:

python htpasswd.py foo bar > passwd_file

There are obvious deficits in the above code, such as minimal input verification, and seeding the encryption with the first two letters of the password. However, I think it illustrates the idea and I encourage someone else to improve it.

And improve it they have. There is now a much better script in http://trac.edgewall.org/browser/trunk/contrib/htpasswd.py


  1. 1. if using Apache 2.x and depending on distribution, it may be called htpassw2
  2. 2. apparently chosen at random by htpasswd2
  3. 3. for obvious reasons, this only works on *NIX systems
  4. 4. The salt is any two characters in the set: [a-zA-Z0-9./]

  • Posted: 2007-11-28 00:09 (Updated: 2008-03-05 05:56)
  • Author: pacopablo
  • Categories: (none)
  • Comments (0)

Enterprise Ready?

In today's IT scene, it is important to know which products are enterprise ready. Cliff Wells provides a useful evaluation of certain popular technologies. He also sets the baseline for what enterprise ready really means. Go see if your technology is Enterprise Ready.

The Mysterious Dell Express Service Code

Love or hate Dell, they do do a few things right. They provide a Service Tag on every PC with which you can get a host of information off their support site. Drivers, manuals, you name it. The service tag is generally on a little black tag someplace on the case. On the tag there is also an Express Service Code. If ever you call for tech support on your Dell computer, you will be asked to enter this number to route your call correctly. Now, you don't actually need it, but it is handy to have.

The service tag is in the BIOS and can be extracted fairly easily, at least from a windows machine with WMI enabled. A simple little python script to do so would look like:

import win32com.client as w32c
comp = "."
wmi = w32c.Dispatch("WbemScripting.SWbemLocator")
wbem = wmi.ConnectServer(comp,"root\cimv2")
colItems = wbem.ExecQuery("Select * from Win32_SystemEnclosure")
for chassis in colItems:
    if 12 in chassis.ChassisTypes:
        continue
    print ("Service Tag: %s" % str(chassis.SerialNumber))
    continue

Not bad. Looks almost identical to it's VBScript counterpart

Now, the real question is: If I have the service tag, but not the express service code, how do I get the express service code?

Good question. There are a few tools1 2 online that will generate an Express Service Code from a service tag.

Digging a bit deeper, we find that the service tag is simply a base 36 number. We also discover that the express service code is simply the bae 10 representation of the service tag. Ah ha! We can handle this! We could always use VBScript to do the conversion3. But that would be too easy, so we'll use Python

print ("Express Service Code: %s" % str(int(service_tag,36)))

Tough, wasn't it?


  1. 1. http://www.creativyst.com/Doc/Articles/HT/Dell/DellPop.htm
  2. 2. http://www.powerdog.com/dellconv.cgi
  3. 3. I hope that this is simply a very bad example of someone not knowing/realizing that there is a much easier way to convert from base 36 to base 10 in VBScript. It can't be THAT bad, can it?

Managing A Network With Trac

I like Trac. That may have been obvious due to hosting the logs for the IRC channel. Or the fact that this site runs on trac1. The simple fact is that Trac is just plain hot.

In my day job, I have the wonderful opportunity to manage two similar, but distinct networks. All-in-all, it's not so bad. However, the older of the two networks, suffers from severe lack of documentation (left to me by The Predecessor). The newer network is still in its infancy. So while there is more documentation, it's still not complete. What's more challenging, is keeping the documentation that is there, up-to-date. Add to this the fact that I really hate "documenting" and it all adds up to a mess.

I've been thinking to myself: "Trac is hot, and documentation is good. There must be some way to merge documentation of a network with Trac". Now, it's easy to say: "Well, Trac has a wiki, just keep the documentation up to date". Great idea, except for the fact that I hate "documenting". On top of that, when things are busy, adjusting documentation is that last thing that I do (and first thing I forget to do).

I agree that Trac is a great start. It's got ticketing, a nice easy wiki, source control integration, just about everything one needs to have good documentation. However, it's lacking the automation. This isn't really Trac's fault, as that's not what it was originally designed for. However, it fits so well, and Trac has such a nice plugin system, it's just begging to be extended.

To this end, I will be starting a Trac network documentation project. Originally, it will be focused on managing a Windows environment with Dell machines, as that's what I'm dealing with. However, I will try to make it general enough to be used in a different network. Some of the features I'm planning are:

  • Automatically pull system information and populate wiki pages. This will include the Dell Service Tag, machine specs, IP information, etc.
  • Association of Asset numbers with wiki pages such that one can reference a machine via asset tag, or search via asset tag and get the relevant info
  • Security for the wiki such that user accessible pages can be created for HOWTOs and other organization wide information
  • Ticket security such that a user can only see their own tickets
  • Automatic tag creation such that each user/system has a unique tag that can be used across the site
  • Aggregate other system info such as:
    • Mail logs
    • Backup logs
    • Anti-virus logs

Basically, the Trac site should be a one stop shop for any network info that is required, be is software licensing, network diagrams, system information, etc.

If this is a project that you'd be interested in, especially if interested in helping out, drop me a line. pacopablo AT pacopablo DOT com

I'll keep you updated.


  1. 1. As is plainly seen by the big Trac logo. I've been meaning to change it, but don't have an ounce of graphic design ability in me. So, if someone is willing to pitch in a logo, I'd be very grateful.

News Box Blogs

I'm not sure where it started, but the first place I saw it, was on trac-hacks.org. I'm talking about the really cool green box that holds the "news". What's even cooler, is combining the green news box with the blog plugin. This is what trac-hacks.org is doing.

The green news box is a little mix of HTML and CSS, and it's dead sexy to have. zachtib was looking for instructions on how to set it up, so here we go

After installing the blog plugin, add the following CSS to the site_css.cs file. It is located in the Trac environment's templates directory.

#newsflash {
        border: solid 2px #8f8;
        width: 400px;
        float: right;
        background: #dfd;
        font-size: 0.8em;
        margin: 0em;
        padding: 0.5em 1em 0.5em 1em;
}
#newsflash h1 {
        font-size: 1.2em;
        padding: 0em;
        margin: 0em;
}
#newsflash .post hr {
        display: none;
}

Once the CSS is inplace, the green box can be created by placing the following at the top of the wiki page on which it should appear.

[[html(<div id="newsflash">)]]
[[BlogShow(blog,news,hidecal=true,num_posts=4)]]
[[html(</div>)]]

Obviously, the options passed to the [[BlogShow]] macro can be adjusted to taste.

Finally, after having done all that, I find a gem that coderanger has created: NewsFlashMacro. While I haven't tested it out, this should provide exactly what the above does, and packaged in to a nice macro.

!PyCon Dreams

As everyone should know, PyCon 2007 is in Addison, TX, February 23rd-25th. It's a time for Python developers to get together and rub elbows.

As it happens, I, unfortunately, am not going. This would be due to a thing called life. Of course, there are going to be a few Trac notables1234 there, and one, in particular, has been bugging5 me to go.

Oh how I would love to go to PyCon. However, it just isn't in the cards right now. Of course, that would all change if, by some miracle, someone paid for my air fare. So, if anyone out there wants to pay for my air fare, I would be ever so grateful. For that wonderful saint that wants to send me to PyCon, contact me at: pacopablo at pacopablo dot com

Here's to wishing! If not, well then perhaps next year.


  1. 1. alect
  2. 2. coderanger
  3. 3. mgood
  4. 4. Tim Hatch
  5. 5. More evidence of my quandary. How can I step down from taunts like that?

  • Posted: 2007-01-16 08:06 (Updated: 2007-01-16 16:49)
  • Author: pacopablo
  • Categories: (none)
  • Comments (0)

Denied!

It's finally official. I didn't get accepted to the Google's Summer of Code. While disappointing, it's also a relief. Perhaps next year I'll take a bit more time to prepare my proposals.

The big question now is what's going to happen with my proposal? Is it going to sit around doing nothing? Or can I catually make something of it?

I definitely have the desire to make something of it. In fact, I have already gotten tracd to run as a windows service. And we're not talking about via InstSrv tracd SrvAny.exe either. So now the big questions are:

  • Packaging via py2exe
  • Bakup interfaces and API
  • Coding

So, we'll see what the summer brings, but I hope to be able to make more progress on Synecdoche.

Of Blogs and Logs

About a week ago, I sat down to finally figure out how to get Postfix to relay mail through a server using SMTP AUTH. It turned out to be quite easy and straight forwad once I was willing to read through the postconf manpage. However, after I was done I realized that I should write down my experience. Lately, my cowoker has been nagging me to write down my adventures. So I went looking for some blog software. I basically had two requirements:

I'm not picky, or anything. Needless to say, my journey down that path left a somewhat sour taste in my mouth. I couldn't believe the dearth of python powered blog software. What a shame! Because I have been working with Trac lately, I decided to see what it had to offer. There did exist a blog macro and I gave it a whirl, but I didn't like it much. I didn't like the fact that the post info (author, date, etc) was above the post instead of below it, and I didn't like summary stuff above the posts.

Now, while contemplating how I could hack the macro and modify it to my preferences, I found the wonderful Tags Plugin. This got me to thinking that being able to tag arbitrary wiki pages and make them part of a blog was a great idea1. After some encouragement from #trac on freenode, I mustered up the will to start coding. Thus was the beginning of the Trac Blog Plugin.

Onto the logs ...

Because of the blog plugin, I've been spending a bit more time in #trac than usual. As I try to be a good boy and share of my knowledge2, I answer questions on the channel if possible. One such question was about an error when trying to load the webadmin plugin. The strange thing about it was that the issue appeared to be in setuptools rather than the plugin. What was more frustrating was the fact that another user had experienced this same issue, but I couldn't remmeber what the solution was3. It was then that I yearned for a log of #trac that I could search, but, alas, it did not exist.

Because of this sense of loss, I set out on yet another journey: find a bot for the #trac channel. Per the suggestion of nuge, I decided to try SupyBot. The most wonderful thing about SupyBot is that it is written in Python. That means I can hack it. After a fairly painless install and a little help from #supybot, I was able to bring to life evil_twin. So now I have a bot that is logging #trac. All I have left is to make those logs accessible via the web. You know what that means, right?

Yup, more Trac integration!


  1. 1. it appears that at least one person thinks this is a bastardization of all that is blog
  2. 2. since many have shared their knowledge with me, for which I am very grateful
  3. 3. if not a complete solution, the work around was to install the webadmin plugin globally using python setup.py install instead of using it as an egg