info-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: cvs commit as root


From: Greg A. Woods
Subject: Re: cvs commit as root
Date: Mon, 10 Dec 2001 14:17:33 -0500 (EST)

[ On Monday, December 10, 2001 at 08:19:47 (-0800), Harry Putnam wrote: ]
> Subject: Re: cvs commit as root
>
> Some things I don't put in cvs.  /etc/passwd /etc/shadow are amongst
> them.  Those are not config files in some sense.  And not likely to
> need version control.  I do have a system in place that diffs thoses
> on a regular basis for security reasons.  And run tripwire as well.

Ah, but they are config files and they do need version control, and you
cannot use something like tripwire on them (well certainly not on
/etc/shadow anyway) because they are changed under the control of users.

What I did when I used CVS to manage system configurations was to keep
just the relevant information in CVS, and to use a program that ran in
place of an interactive editor under 'vipw' to affect changes in the
live /etc/passwd file.  I'll attach the versions of the scripts I used
for managing SunOS-4 /etc/passwd (without /etc/shadow).  They allow you
to write a template passwd file that has the keyword "SAVED" in the
passwd and shell fields if the value from the live /etc/passwd file is
to be used (with an optional default shell name to be used if the
account is being created anew).  I.e. they implement a very simple macro
processor that effectively merges the template and old file to create a
new file.  This way I can add new accounts to the system (you should
NEVER remove an account -- only disable it), and manage some of their
attributes, such as home-directory, UID, GID, etc. all with version
tracking in CVS.

> This layer you speak of.  I don't really get the big picture I think.
> Is there documentation about this kind of setup?  Especially as it
> pertains to cvs?  I get the feeling people are describing something
> like:
> 
> {$CVSROOT} <=>interplay1 <=> {checked out module} <=> inerplay2 {system}
> and some kind of makefile/scripting setup that automates interplay1
> and interplay2.
> 
> The checked out module being the buffer you speak of.

There's nothing magic necessary between $CVSROOT and the checked out
working directory (though having commitinfo and loginfo scripts to help
validate changes and e-mail other admins notifications of changes are
very good ideas).

All you really need is the process of copying the files from the checked
out working directory to the live system, including setting their

> The makefiles syntax threw me yes, but I'm really not a stranger to
> shell scripting.  Using ksh, sh and bash, I've probably written well
> over 100 homeboy scripts, some of them semi complicated. Not claiming
> any skill at this, just that I am familiar with basic shell scripting,
> still that makefile stuff looks intimidating to me.  he he.

Makefiles are just lists of dependency rules with shell scripts that
implement the actions necessary to maintain the dependencies.
Traditional make syntax is very trivially simple -- it's the concept
that's powerful.  Modern makes often hide great complexity in their
default macros, such as the stuff in /usr/share/mk on *BSD systems.

The only complication with traditional make is that the macro facility
in make is very much like shell variables, with a somewhat conflicting
syntax, though it's possible to use a unique syntax in make that's less
easy to confuse with shell syntax, the only caveat being that you have
to use two '$' to get one through to the shell.  Eg. in a make rule you
have to write:

        for foo in 1 2 3 ; do echo $$foo ; done

in order for make to call the shell as:

        sh -c 'for foo in 1 2 3 ; do echo $foo ; done'

Of course you also need to know about the default macros make sets when
it's evaluating a rule, such as '$@' which is substituted with the name
of the target file.

-- 
                                                                Greg A. Woods

+1 416 218-0098;  <address@hidden>;  <address@hidden>;  <address@hidden>
Planix, Inc. <address@hidden>; VE3TCP; Secrets of the Weird <address@hidden>


# Makefile fragment using the vipw editor trick to ensure locking of the
# password file
#
/etc/passwd: etc/passwd
        @if [ -r $@ ] ; then \
                if cmp $? $@ > /dev/null ; then \
                        :; \
                else \
                        echo "VISUAL=\"`pwd`/../vipwsh\" vipw"; \
                        VISUAL="`pwd`/../vipwsh" vipw; \
                        if [ -s vipwsh.out ] ; then \
                                ds=`date |sed 
's/^\(.............\):.*\([0-9][0-9][0-9][0-9]\)$$/\1:.*\2$$/'`; \
                                sed "1,/$$ds/d" vipwsh.out; \
                        fi; \
                fi; \
        else \
                echo "WARNING: $@ was missing!"; \
                echo "VISUAL=\"`pwd`/../vipwsh\" vipw"; \
                VISUAL="`pwd`/../vipwsh" vipw; \
                if [ -s vipwsh.out ] ; then \
                        ds=`date |sed 
's/^\(.............\):.*\([0-9][0-9][0-9][0-9]\)$$/\1:.*\2$$/'`; \
                        sed "1,/$$ds/d" vipwsh.out; \
                fi; \
        fi

#! /bin/sh
:
#
#       vipwsh.sh - used as $EDITOR for vipw
#
#ident  "@(#)cf:$Id: vipwsh.sh,v 1.7 1997/03/04 04:46:59 woods Exp $"

TMPDIR="${TMPDIR:-/tmp}" ; export TMPDIR

PATH="/usr/5bin:/usr/bin:/usr/ucb:/usr/etc:/sbin"
export PATH

CFDIR="`dirname $0`"

EDITFILE="$1"

echo "" >> vipwsh.out
echo "New run started:  `date`" >> vipwsh.out
echo "" >> vipwsh.out

(
        cut -d: -f1,2,5,7 /etc/passwd | \
        cat - etc/passwd | \
        awk -f $CFDIR/mkpasswd.awk LOG=vipwsh.out | \
        sort -t: -n +2 > $EDITFILE
)

exit $?
#! /usr/bin/awk -f
#
#       mkpasswd.awk - create a new password file
#
#ident  "@(#)cf:$Id: mkpasswd.awk,v 1.6 1996/11/04 19:17:54 woods Exp $"

BEGIN {
        FS=":";
        haveuid[""] = "";
        oldgcos[""] = "";
        oldpasswd[""] = "";
        oldshell[""] = "";
}

# reading old passwd input
# (generated by 'cut -d: -f1,2,5,7 /etc/passwd')
#
NF == 4 {
        userid = $1;
        passwd = $2;
        gcos = $3;
        shell = $4;
        # maybe we should key off uid?
        haveuid[userid] = 1;
        oldpasswd[userid] = passwd;
        oldgcos[userid] = gcos;
        oldshell[userid] = shell;
}

# reading the new password file (old V7 format)
#
# if passwd field is "SAVED", it'll either be the one from /etc, or "NEW"
# if GCOS field is "SAVED,\(.*\)", it'll either be the one from /etc, or "\1"
# if shell field is "SAVED,\(.*\)", it'll either be the one from /etc, or "\1"
#
NF == 7 {
        userid = $1;
        if (haveuid[userid] != 1) {
                printf("ADDED = '%s'\n", $0) >>LOG;
                if ($2 == "SAVED") {
                        passwd = "NEW";
                } else {
                        passwd = $2;
                }
        } else if ($2 == "SAVED") {
                passwd = oldpasswd[userid];
        } else {
                passwd = $2;
        }
        uid = $3;
        gid = $4;
        if ($5 ~ /^SAVED,/) {
                ngcos = substr($5, 7);
                if (haveuid[userid] != 1) {
                        gcos = ngcos;
                } else {
                        gcos = oldgcos[userid];
                        if (ngcos != gcos) {
                                printf("%s: orig gcos = '%s' user gcos = 
'%s'\n", userid, ngcos, gcos) >>LOG;
                        }
                }
        } else {
                gcos = $5;
                if (gcos != oldgcos[userid]) {
                        printf("%s: WARNING: OGCOS = '%s' NGCOS = '%s'\n", 
userid, oldgcos[userid], gcos) >>LOG;
                }
        }
        home = $6;
        if ($7 ~ /^SAVED,/) {
                nshell = substr($7, 7);
                if (haveuid[userid] != 1) {
                        shell = nshell;
                } else {
                        shell = oldshell[userid];
                        if (nshell != shell) {
                                printf("%s: orig shell = '%s' user shell = 
'%s'\n", userid, nshell, shell) >>LOG;
                        }
                }
        } else {
                shell = $7;
                if (shell != oldshell[userid]) {
                        printf("%s: WARNING: OSHELL = '%s' NSHELL = '%s'\n", 
userid, oldshell[userid], shell) >>LOG;
                }
        }
        printf("%.8s:%s:%d:%d:%s:%s:%s\n", userid, passwd, uid, gid, gcos, 
home, shell);
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]