Secure passwordless logins

Posted by Graham Stratton Mon, 26 Jun 2006 15:12:00 GMT

SSH is the the standard way of communicating between UNIX machines, and there are various ways of transferring files over SSH and doing other clever stuff.

However, if you need to automate a process, such as a backup, or just login to lots of machine regularly, then needing to enter passwords for each connection is an issue. So, here’s how to avoid the pain.

First of all, you need to generate a key on the client machine, using the command
ssh-keygen -t rsa

You’ll be promted for where you’d like the key pair; the default location is usually fine. You’ll also be asked for a password. This password will need to be entered before the password can work. So if you want a process to be able to use SSH logins without you ever entering a password, leave this blank.

Of course, this is a bit insecure, since anyone who gains access to your account on your client machine also has access to the other machine. Once you have a large group of machines all of which have passwordless logins to one another, you can appreciate the world becomes quite a dangerous place.

What you can do, if you need automated login with reasonable security, is to restrict the commands that the key can access; more of this is a second.

The next thing to do, once you have generated your key, is to copy your public key (by default id_rsa.pub), to the machine you wish to log in to. (It is your private key that enables you to decrypt what is encrypted using your public key. Your private key stays on your machine in a non-public readable file.) Once there, you should append it to the authorized_keys file:

cat id_rsa.pub >> ~/.ssh/authorized_keys

At this stage, if you only wanted to the key to be used for a single command, you could add some restrictions before and on the same line as your public key

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="ls"

You can of course use multiple keys for different purposes.

If you want to generate a passwordless login just to save yourself from typing, then you should give a password when generating your key. You will then need to give this password when you want to SSH into the other machine.

I know, that’s gained you nothing. But, that’s not the end. There’s a program called ssh-agent, which when run from a session, will remember your password for that session.

no comments

Formlib edit forms

Posted by Graham Stratton Wed, 17 May 2006 20:51:00 GMT

There seems to be a bit of a shortage of simple documentation for formlib, so I’ll attempt to do my bit. This one’s just a custom edit form. Replacing the standard edit form allows you to put text around the form, and to change what actions can be executed on submit. In this case, we extend the render method to redirect to the object’s default view after editing, instead of returning to the edit view.

from zope.app.pagetemplate import ViewPageTemplateFile
from zope.formlib import form
from interfaces import ITextPage

class EditView(form.EditForm):
    form_fields = form.Fields(ITextPage)

    base_template = form.EditForm.template
    template = ViewPageTemplateFile('textpageedit.pt')

    def render(self):
        if self.errors is None or self.errors:
            return super(EditView, self).render()
        self.request.response.redirect('.')

As you can see, the default template is replaced, but is made available under the name ‘base_template’. This means that it can be accessed from the replacement page template like this:

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:tal="http://xml.zope.org/namespaces/tal" 
      xmlns:metal="http://xml.zope.org/namespaces/metal" 
      metal:use-macro="view/base_template/macros/main">

<body>
<div class="section" metal:fill-slot="extra_info">
<h3>Edit this page</h3>
<p>Here you can put some instructions about editing the page.</p>
</div>
</body>
</html>

Take a look at the base template at formlib/pageform.pt to see what other METAL slots are available.

Posted in  | no comments

Zope 3.3-ification

Posted by Graham Stratton Sat, 13 May 2006 11:03:00 GMT

Moving from zope 3.2 to 3.3 requires a few changes. I thought I’d describe the ones I made here.

There are a number of packages which have moved out of zope.app, up into the zope package. In my case, I had to update references to:

  • zope.app.annotation
  • zope.app.copypastemove
  • zope.app.traversing
  • zope.app.dublincore

Due to the changes in skinning I had to modify my skin declarations. First I had to write some python to define my skin in skin.py:

from zope.app.rotterdam import Rotterdam

class MySkin(Rotterdam):
    """My default skin""" 

And then I had to replace the browser:layer and browser:skin configuration:

  <browser:layer name="mylayer" />
  <browser:skin name="MySkin" layers="mylayer rotterdam default" />
with:
<interface
    interface=".skin.MySkin" 
    type="zope.publisher.interfaces.browser.IBrowserSkinType" 
    name="MySkin" 
    />

You’ll notice that there is no longer a layer definition. Defined like this, a skin merely inherits from its parent.

However, the browser: ZCML directives will accept a skin object as a ‘layer’ argument.

There is a handy base class for browser pages: zope.publisher.browser.BrowserPage; this used to be zope.formlib.Page. A simple page can implemented using it like this:

from zope.publisher.browser import BrowserPage
from zope.app.pagetemplate import ViewPageTemplateFile

class MyPageRenderer(BrowserPage):
    __call__ = ViewPageTemplateFile('mypageview.pt')

    def method(self):
        """"A method to support the view""" 

and configured like this:

<browser:view
    for="mycms.interfaces.IMyPage" 
    name="index.html" 
    class=".mypageview.MyPageRenderer" 
    menu="zmi_views" title="View" 
    permission="zope.View" 
    />

no comments

Named templates

Posted by Graham Stratton Fri, 12 May 2006 12:34:00 GMT

Named templates are a feature I hear mentioned a bit, but haven’t understood whether I want to use or not. So here’s a little investigation into how to use them and some thoughts about what they might be used for.

Named templates are part of the formlib package, and a suggested use is for forms which might want to have different appearance at different times, though using the same view. Named templates are looked up by view and template name only.

One use for named templates might be in a CMS where you wish to have a couple of default page layouts; say, for example, one type which has a right-side bar for latest news, and one which doesn’t. For each page, you might want the user to be able to select which template to use.

Or you might the top page of your site to have a different template. All the page view would need to do is to check for whether the page implements ISite, and if so use the home page template instead of the default template.

Posted in  | no comments

Views

Posted by Graham Stratton Fri, 12 May 2006 09:26:00 GMT

One thing that got me for a while with Zope3 is how view lookups work. A view is looked up by the object, the request and the view name. What does that mean? Surely the object comes from the request anyway?

Yes, but the lookup is done by interfaces. So the object is likely to provide IMyObject, the request IBrowserRequest, and the view name something like index.html. When you defined your object, your will probably have also defined a browser view for index.html, and this is what will be found.

A view for ”*” will be registered for Interface, so the lookup will match any object type, since all interfaces inherit from Interface. So interface lookup climbs the inheritance tree. I don’t know how it deals with multiple inheritance, though. Probably in the same way as Python (which changed in version 2.2).

So what is a view? Well, it’s a class which adapts an object and a request. That means that what you instantiate the class, you pass in an object and a request. Okay, but then what? Well, when you call that instance, it should return the HTML for that view.

Okay, that’s that sorted then. Let’s more on to content providers. A content provider adapts an object, a request and a view to IContentProvider. IContentProvider requires that the object have attributes request, context (the object), and _parent_ (the view). It should also provide an update() method, and a render() method, which returns the HTML.

So, a content provider lookup discriminates against the view. What does that do for us? Well, we might have a content provider contains the CSS loading code. We might want a different stylesheet for our management and non-management screens. So if all our views either implement IMyManagementView or IMyNonManagementView, then by looking up a content provider called, say cssimport, then we could get the appropriate one for our view, assuming that we had registered content providers for both Interfaces.

Posted in  | no comments

Views, viewlets and content providers

Posted by Graham Stratton Thu, 11 May 2006 10:58:00 GMT

I’ve always had the feeling that understanding the fundamentals of Zope3 won’t take too much longer. Hopefully I’m now one step nearer. In this article I hope to explain how views, viewlets and content providers fit together.

Views have been around in Zope3 since the beginning, whereas viewlets and content providers appeared with formlib in 3.2.

Let’s deal with content providers first. The contentprovider module is very simple. It merely defines an interface for a content provider, which requires an object providing it to have an update() and a render() method. The update() method will be called first so that object can be modified in light of the request (eg form data). Then the render() method is called which should return the final HTML.

The second thing that the contentprovider module does is to enable the ‘provider’ attribute in TAL, which facilitates the use of content providers in templates. Note, though, that when many content providers exist in the same template, the two-stage rendering process is not honoured across providers. Viz., the update() and render() methods will be called on the first provider, then on the second, and so on, instead of all the update() calls preceding all the render() calls.

So, how about a minimal code example? Well, here we go… create a new package called boring, and install a slug in etc/package-includes to load it. Now create a _init_.py like this:

from zope.interface import implements, Interface
from zope.component import adapts, provideAdapter
from persistent import Persistent
from zope.contentprovider.interfaces import IContentProvider
from zope.publisher.interfaces.browser import IDefaultBrowserLayer

class MyContentProvider:
    implements(IContentProvider)
    adapts(Interface, IDefaultBrowserLayer, Interface)

    def __init__(self, context, request, view):
        self.context = context
        self.request = request
        self.__parent__ = view

    def update(self):
        pass

    def render(self):
        return u'<h1>Look Ma, I rendered something!</h1>'

provideAdapter(MyContentProvider, name="boring.MyContentProvider")

class IBoring(Interface):
    """Interface for a really boring content object""" 

class Boring(Persistent):
    implements(IBoring)

Create a page template called contentprovider.pt like this:

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:tal="http://xml.zope.org/namespaces/tal" 
      xmlns:metal="http://xml.zope.org/namespaces/metal" 
      metal:use-macro="context/@@standard_macros/page">

<head>
  <title metal:fill-slot="title">Test page</title>
</head>
<body>
<metal:slot fill-slot="body">
  <tal:block replace="structure provider:boring.MyContentProvider" />
</metal:slot>
</html>

And finally create the configure.zcml file to tie it all together like this:

<configure
    xmlns="http://namespaces.zope.org/zope" 
    xmlns:browser="http://namespaces.zope.org/browser" 
    i18n_domain="zope" 
    >

  <class class=".Boring">

    <factory
        id="boring.Boring" 
        description="Boring factory" 
        />

  </class>

  <browser:page
      for=".IBoring" 
      template="contentprovider.pt" 
      name="contentprovider.html" 
      permission="zope.View" 
      />

  <browser:addMenuItem
      class=".Boring" 
      title="Boring object" 
      permission="zope.View" 
      />

</configure>

Then start zope, log in to the ZMI, create a Boring object called boring, and go to /boring/@@contentprovider.html, and should should see the page provided by our content provider. That’s about as simple as it gets.

So what can we do with our content provider now we have one? Well, one thing we can do is to use a viewlet manager as a content provider, so in my next article I’m going to show how to set up viewlets and register them with a viewlet manager.

Posted in  | no comments

Fixing fonts

Posted by Graham Stratton Wed, 03 May 2006 14:07:00 GMT

After upgrading X to x.org 7.0, I found that some fonts which had previously been anti-aliased were no longer.

By running ‘dpkg-reconfigure fontconfig-config’ I restored my display to its former glory. Now all I need to do is to get suspend to work, and I won’t need a Mac.

Posted in ,  | no comments

Hiding email addresses from spam bots

Posted by Graham Stratton Sun, 12 Mar 2006 13:59:00 GMT

Anyone who has put their email address on a web site with reasonable ratings knows that this is a recipe to get lots of spam.

So, what can a girl do? Well, there are plenty of options.

Lots of people have varitations on the idea of modifying the address, so that the user has to change the address before sending the mail. This is likely to confuse a lot of users, and there I consider it to be unsuitable for non-technical sites. Even displaying your email address as ‘joe AT bloggs DOT com’ is likely to cause many users grief.

Another idea is to HTML-encode the address in both the text and the mailto: link. Some people are of the opinion that having an email address public is fine, and that all spam bots work by looking for mailto: links.

One suggestion is to make the address an image, which acts as a mailto: link once it is pressed, courtesy of Javascript.

no comments

debian keys

Posted by Graham Stratton Fri, 10 Feb 2006 14:53:00 GMT

I just installed kanotix 2005-4, but when I came to install some new packages, I got a warning saying that the packages cannot be authenticated.

A bit of googling suggested that I needed to update the debian keys. This should easily be done with ‘apt-key update’, but that returned an error saying:

ERROR: Can’t find the archive-keyring Is the debian-keyring package installed?

I installed the package, but the error remained. It seems this is a bug in debian. Changing

ARCHIVE_KEYRING=/usr/share/keyrings/debian-keyring.gpg

to

ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg

in /usr/bin/apt-key line 12

allowed me to run ‘apt-key update’, which downloaded 903 keys but then hung. But apt-get update still reported

E: Some packages could not be authenticated

and apt-get install still gave the error

The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 010908312D230C5F

gpg—keyserver wwwkeys.eu.pgp.net—recv-keys 2D230C5F

fetches the relevant key successfully.

It should then be possible to it them to the keychain with

gpg—armor—export 2D230C5F | apt-key add -

but that command returns

gpg: no writable keyring found: eof gpg: error reading `-’: general error gpg: import from `-’ failed: general error

Eventually I realised that this is an environment issue. If I ran these commands as root instead of using sudo, the keys can be added.

Posted in ,  | no comments

A good website design!!

Posted by Graham Stratton Thu, 02 Feb 2006 19:46:00 GMT

See here

no comments

Older posts: 1 2 3 4 5 6