UNIX Password, Roles & Node Management: Generator Details
The generator, password_generator.pl, is one of the three core scripts in Password Management. It ensures the correct users are built into the work files on a per-node basis quickly and sanely.
You must specify one of the following three arguments, followed by a list of names:
-R list
-R
obtains the list of nodes to work on by role name. list
in this
context is one or more role names. You can specify as many roles as you want,
or let list
be empty which indicates all roles are to be built.
Example:
# ./password_generator.pl -R AdminUnixUsers DevUsers HelpdeskAdmins
-E list
-E
obtains the list of nodes to work on by environment. list
in this
context is one or more valid environments. You can specify as many environments
as you want, or let list
be empty which indicates all environments are to be built.
Example:
# ./password_generator.pl -E prod/database prod/www ga/atlanta/facility01/misc/async
-N list
-N
obtains the list of nodes to work on from list
. list
in this context
is one ore more active inventory nodes. You can specify as many nodes as you
want, or let list
be empty which indicates all active nodes are to be built.
Example:
# ./password_generator.pl -N node01.domain.com node02.domain.com
-d
-d
and
-v
do not imply each other.
-v
-d
and -v
do not imply each other.
-h
-C
-A
-R
, -E
, or -N
as above.
The steps to decide the users for the node will be shown, but no work will actually
be done. This is quite useful for when you want to see why (or why not) users
were installed onto a node or why they have the sudo permissions they do.
list
into nodenames.If -R
is specified, then the roles are translated into environments (via
Covad::Pwman::Roles::pwman_get_envs_by_role
).
Those environments (or the contents of -E
, if it was specified) are translated into
nodes (via Covad::Pwman::Search::pwman_find_nodes_by_tag
).
Those nodes (or the contents of -N
, if it was specified) becomes the nodelist we work from.
+ENV
tagsCovad::Pwman::Parsers::pwman_parse_ncf
).
+ENV
environment settings. Covad::Pwman::Roles::pwman_role_builder
does all of this for us,
Each environment specified by the +ENV
tag is examined in the following manner:
prod/www/application
has three parts: prod
, www
, and application
). A final,
implicit environment is prepended to this list: the /
, or top-level, environment.
Each environment is examined in turn, underneath the pwman.environments directory. If
the environment's directory is not found, that environment is discarded.
If a role-users file is found in that directory, it is parsed as if it is a
role-listing file format. The roles listed in this file should
exist in the pwman.roles_dir directory (if it doesn't, that role is discarded).
The role is parsed, and the users are extracted, along with their sudo directives. These users
will be put into each node that lives in and under this environment.
+NOINHERIT
set, then any roles that
preceded this environment part (except the implicit top-level role /
) will be discarded.
If the role-users file has the special tag +EXCLUSIVE
set, then any other role
in any environment hierarchy will be discarded (except the implicit top-level role /
).
If there are more environment parts or full environments to examine, they will be, but
the roles will not be expanded. If one or more environment parts have +EXCLUSIVE
defined,
the first one found will be used.
:
), a 'groups' entry (prefixed with a vertical bar |
), or
a direct username (which is a deprecated method of putting users onto nodes and will issue
a warning).
The outcome of this is a large-ish hashreference that looks a bit like this:
$ref = { user_list => { usera => { undef, }, userb => { 'role-name' => 'env-set-by', 'role-name' => 'env-set-by', }, group-user => { '_data' => 'group-name', }, hack-user => { '_data' => 'hack-user:x:200:200:hack-user:homedir:/bin/sh', }, }, is_exclusive => 'env', no_inherit => [ env, env, ], };
If a user exists in the user_list
hash, then that user must be installed onto the node
we're working on. If the user has any role attributes assigned to it (as in userb
, above)
then those attributes are interpreted to be role names whose sudo directives need to apply
to this user. 'groups' users have a special attribute _data
, which is a scalar containing
the name of the group file from which they were referenced; this group file can be found
in pwman.groups_dir. 'hack' users also have a special attribute _data
, which is a
scalar containing the actual passwd entry that should be used for this user.
password_generator.pl uses two types of plugins: obtain and gen. They're detailed below, along with their phases.
Each obtain plugin must be able to retrieve the following information for a user given a username:
obtain_pre plugins are run, one at a time, in alphabetical order. Each plugin loops
through the list of users and tries to resolve them into a user entry. If no entry can
be found, the obtain_pre plugins skip it and go on to the next one. User entries are
cached by username, so if a user is already resolved by a prior obtain_pre plugin
it is not re-resolved, because it's already in the cache. This cache is nothing more
elaborate than a hashref indexed by username. Entries that already
exist (that have already been looked up and resolved) are by default skipped on sequential
plugins. This behavior can be changed with the pwman.pg.obtain.use_first_match property.
Changing this property to undef
or unset will ignore a user entry's presence if the user
exists in a seperate authentication source, and the last source with a matching username
will be used. This property is enabled by default and should not be unset unless you're
clear about what users are in which data source.
Examples:
If the user isn't found, then the entry is not generated. pwman.pg.obtain.use_first_match has no effect here, because there is only one source to work through.
root
. Or you might
have many different root
accounts, broken down by environment (so you have one
root
password for your development systems, and one root
password for your
colocated servers in Georgia, and one root
password for your customer-facing
nodes, and so one). These are called hacks. They act as overrides to prevent the
accidental removal of a critical user account. A hack entry looks like a line
directly out of a functional /etc/passwd file:
root:hYukworb4s0:0:Super-User:/:/sbin/sh
and is located in the directory defined by the pwman.hacks_dir property. Hacks files
can be called whatever you want. In our above example on different root
passwords,
you might call them root-dev, root-colo-ga, and root-dmz. The only thing that
would be different between these three hacks files would be the crypt()
ed password
string in the second field.
In order to translate these 'hacks' entries into actual entries, we use a plugin, and we call it obtain_pre_hacks. The only thing this plugin does is split up the line read by the role parser, and re-assigns it to the user hashref in the proper format.
The plugin ordering looks now like this:
daemon
, bin
, lp
, etc) and that actual employee user accounts
must come from AD. The ordering of the obtain plugins should look like this, with
pwman.pg.obtain.use_first_match set to true
:
Note that if there are duplicate user accounts in NIS or AD, the account in NIS will win, because use_first_match is in effect. Changing use_first_match to unset will reverse that behavior - the duplicate account in AD will be used. However, this will also override any 'hack' entries and that might not be desirable.
You can stack as many obtain plugins as you feel you need to. (I honestly don't believe you should have more than 1 authorative source, but there may be times when this is unavoidable, and so the flexibility exists).
sprintf
). gen_post phase
plugins can perform checking on the generated work files after they've been written.
the Covad::Pwman manpage, the Covad::Pwman::Parsers manpage, the Covad::Pwman::Roles manpage
Jon Gilbert <jong@jong.org>
$Id: pwman_docs_generator.pod,v 1.2 2005/10/20 08:46:34 jgilbertsjc Exp $