Posts Tagged ‘System Administration’

Solaris 10 Root Shell Recovery

Sun Solaris

Solaris


Contrary to recommendations from seasoned Unix admins, it’s perfectly acceptable to change the root shell from the bourne shell to something like bash. The most common reason to leave the root shell alone usually goes something like, “you need a valid and statically linked shell defined in /etc/passwd to boot into single user mode if you need to recover your system.”

There’s a really nice list of Solaris root shell misconceptions published at http://www.roble.com/docs/sol_root_shell.html.

Fortunately for me, this isn’t the case in Solaris 10. While setting up a new Solaris 10 system today, I accidentally set root’s shell to /sbin/bash instead of /usr/bin/bash. /sbin/bash doesn’t exist, so I could no longer log into the system.

Luckily, this is a system with a Dell RAC card setup for remote console access. I logged into the RAC and issued a “graceful shutdown” power off command, which Solaris responded to nicely and brought the system entirely down. Once I powered the system back on, it’s simply a matter of booting into single user mode by passing the -s flag to the kernel.

Solaris 10 is smart enough to fall back to /sbin/sh if it can’t invoke the shell defined in /etc/passwd booted into single user mode. So long as you don’t horribly mangle /sbin/sh and the libraries it’s linked to, you’ll be fine changing the root shell to anything you like.

Here’s how it went:
2009-04-01_1708
2009-04-01_1709
2009-04-01_1710
2009-04-01_1711
2009-04-01_1714

 

My Love of Puppet

PuppetConsider the following statement in a puppet manifest (think of a manifest as a script).

node "subversion.math.ohio-state.edu" {
    subversion::server::webrepository {
        "support": path => "/var/svn/support";
        "test":    path => "/var/svn/test";
    }
}

Without describing the problem this puppet snippet addresses, one might guess that I need to configure two subversion repositories, available via HTTP on the host “subversion.math.ohio-state.edu”.

The reason I absolutely *love* Puppet is the above code is all there is to this entire problem. Think about all the work that actually needs to happen to setup a subversion repository on a SSL enabled web server:

  • Install apache
  • Setup SSL certificates
  • Install subversion and dependencies
  • Setup apache virtual host with mod_dav_svn
  • Setup apache htaccess for access control to the repositry
  • Punch holes in the firewall (80, 443)
  • Create the blank repository with svnadmin
  • Ensure the repository is owned by apache
  • Ensure post-commit hooks are put in the right place and executable

Now, this is a lot of work, and I’ve already had the need to create new subversion repositories on other hosts. Because I’ve already modeled this problem in puppet, it’s trivial for me to bring up subversion servers on arbitrary hosts. I just re-use the block you see above.

Now, for the tricky part… Here are the modules that actually model the subversion repository in question.

Note that I’ve left out the classes which model other aspects of the host in question. For example, web::baseserver::ssl, firewall::input-port, and site-files::certificates (SSL Certs).

# Subversion Module.

class subversion::server inherits subversion {
    File {
        mode => 0640,
        owner => "apache",
        group => 0,
        require => [ User["apache"], Package["subversion"] ]
    }

    define webrepository ($path = false) {
        File {
            owner => "apache",
            group => "0",
            mode => 0660
        }
        $path_real = $path ? {
            false => "$name",
            default => "$path"
        }
        include subversion::server
        repository {
            "$name": path => "$path_real";
        }
        file {
            "$path_real":
                recurse => true,
                require => [ User["apache"], Repository["$name"] ];
            "$path_real/hooks":
                ensure => directory;
            "$path_real/hooks/bin":
                ensure => directory;
            "$path_real/hooks/bin/commit-email.pl":
                content => template("subversion/hooks/bin/commit-email.pl"),
                mode => 0770;
            "$path_real/hooks/post-commit":
                content => template("subversion/hooks/post-commit"),
                mode => 0770;
        }
    }

    include web::baseserver::ssl

    file {
        "/var/svn":
            ensure => directory;
        "/etc/httpd/htaccess/authz_svn.htaccess":
            content => template("subversion/htaccess/authz_svn.htaccess.erb");
        "/etc/httpd/htaccess/authz_svn.users":
            content => template("subversion/htaccess/htpasswd.mathsvn.erb");
    }
    web::vhost {
        "subversion":
            template => "subversion.conf.erb";
    }
    package {
        "subversion-perl":;
        "mod_dav_svn":;
    }
}

class subversion {
    $authz_svn_access_file = "/etc/httpd/auth_SVNAccessFile.math"
    $auth_svn_users_file = "/etc/httpd/auth_htpasswd.mathsvn"
    $svn_base_parent_repo = "/var/svn"
    Package {
        ensure => present
    }
    package {
        "subversion":;
    }

    define repository ($path = false) {
        $path_real = $path ? {
            false => "$name",
            default => "$path"
        }
        include subversion
        # Create a blank repository.
        exec {
            "svnadmin_create_$path_real":
                command => "/usr/bin/svnadmin create '$path_real'",
                require => [ Package["subversion"] ],
                creates => "$path_real";
        }
    }
}