Forum: Cfengine Help
Subject: I think I have created a solution for keeping admin passwords in sync
on AIX
Author: raymondcox
Link to topic: https://cfengine.com/forum/read.php?3,20974,20974#msg-20974
I have posted a couple of times about syncing select AIX users between all of
my machines. I initially had a file that required me to manually update the
password entries. That turned out to be a pretty bad idea, and I don't think it
really fits into the CFengine philosophy.
The latest solution I have come up with is a variation on the first method with
a little LINUX flavor thrown in, it seems to do what I want most of the time.
This first section works exactly as I expect and seems pretty reliable. A file
called /var/cfengine/cache/cfsec_shadow gets generated with the proper values.
#
# Used to update the file /etc/security/passwd on an AIX system by creating a
file that mimics
# the format of the /etc/shadow file in LINUX.
# Dependancies:
#
# /fixes/scripts/cfpasswd
# Perl script used for dumping the passwords of the admin users defined in the
slist admin_users.
# /fixes/scripts/cfpasswd:
# #!/usr/bin/perl
#
# $_user = $ARGV[0];
#
# ($account, $passwd, $uid, $gid, $quota, $comment, $gcos, $home, $shell)
= getpwnam($_user);
# print "$passwd";
#
#
#
body common control {
bundlesequence => { "harvest_passwords" };
inputs => { "adminlist.cf",
"/var/cfengine/inputs/cfengine_stdlib.cf", "/var/cfengine/inputs/site.cf", };
}
#
bundle agent harvest_passwords {
files:
tssdev::
"/etc/security/passwd"
handle => "detect_master_AIX_password_change",
comment => "Check to see if the /etc/security/passwd file has been
updated since the last run",
changes => detect_all_change,
classes => if_repaired("password_was_updated");
methods:
password_was_updated::
"update_passwords" usebundle =>
regen_AIX_mock_shadow_file_for_admin_users;
}
# Convert the entries in /etc/security/passwd on AIX from:
#
#tstusr1:
# password = bNR2bnq./xYWM
# lastupdate = 1299424296
# flags = ADMCHG
#
#tstusr2:
# password = 7f23WTTmyCHg6
# lastupdate = 1299165612
# flags = ADMCHG
# TO:
#
#
#tstusr1:bNR2bnq./xYWM:
#tstusr2:7f23WTTmyCHg6:
#tstusr3:8fPb6gQQrBDGA:
#tstusr4:Wdffu2kUDRM4I:
bundle agent regen_AIX_mock_shadow_file_for_admin_users
{
files:
aix::
"/var/cfengine/cache/cfsec_shadow"
handle => "mock_shadow_file",
comment => "Updating passwords in /etc/shadow and /etc/security/passwd",
edit_defaults => empty,
create => "true",
classes => if_ok("shadowpass_is_go"),
edit_line => insert;
methods:
shadowpass_is_go::
"update_admin_pass" usebundle => passlist;
}
bundle edit_line insert
{
vars:
"admin_users" slist => { "tstusr1", "tstusr2", "tstusr3", "tstusr4" };
"admin_pass[$(admin_users)]" string => execresult("/fixes/scripts/cfpasswd
$(admin_users)","useshell");
insert_lines:
"$(admin_users):$(admin_pass[$(admin_users)]):";
}
##########################################################################
This next part is where I start to have a little unpredictable behavior. I seem
to be able to update the password reliably, but the lastupdate field does not
always get set as I would expect. The last field that I have attempted to deal
with is the flags section, I have not yet figured out how to replace the value
ADMCHG with a space. cf-promises yells at me every time I attempt it, but in
all fairness I have not decided that I really need to clear it yet.
bundle agent passlist
{
vars:
"myepoch" string => execresult("/usr/bin/date +%s","useshell"),
policy => "free";
files:
"/tmp/passwd"
handle => "update_etc_security_passwd",
comment => "Keep passwords up to date",
edit_line => security_edit("$(myepoch)");
reports:
aix::
"Sending: $(myepoch) to security_edit";
}
##########################################################################
bundle edit_line security_edit(epoch) {
vars:
"mypasswd" int =>
readstringarray("mypasswd_array","/var/cfengine/cache/cfsec_shadow","#[^\n]*",":",200,10000);
"admchg" string => "ADMCHG";
#"newadmchg" string => " ";
"shadow_users" slist => getindices("mypasswd_array"),
policy => "overridable";
replace_patterns:
"^(\tpassword) = (?!$(mypasswd_array[$(shadow_users)][1])).*$"
handle => "update_password_in_file",
comment => "Updates the hashsed password in /etc/security/passwd
based on a single reference system",
replace_with => new_password("$(mypasswd_array[$(shadow_users)][1])"),
select_region => user_region("$(shadow_users)");
"^(\tlastupdate) = (?!$(epoch)).*$"
handle => "keep_changed_password_from_expiring",
comment => "Emulates the admin changing their own password on each
machine",
replace_with => new_epoch("$(epoch)"),
select_region => user_region("$(shadow_users)");
#"^(\tflags) = $(admchg).*$"
#handle => "clear_admchg_flag",
#comment => "Remove the requirement for admins to change their
password at first login This should not apply to the reference system",
#replace_with => clear_admchg,
#select_region => user_region("$(shadow_users)");
}
##########################################################################
body replace_with new_password(password) {
replace_value => "$(match.1) = $(password)";
}
body replace_with new_epoch(newepoch) {
replace_value => "$(match.1) = $(newepoch)";
}
#body replace_with clear_admchg {
#
#replace_value => "$(match.1) = "$(newadmchg)";
#
#}
##########################################################################
body select_region user_region(userid) {
select_start => "^$(userid):$";
select_end => "^(\tflags) = .*$";
#include_start_delimiter => "true";
#include_end_delimiter => "true";
}
##########################################################################
I really like CFengine, but sometimes it drives me a little nuts. edit_line is
extremely powerful at being able to replace formatted text, however I have not
found a function that allows me to obtain a value from formatted text.
The recreation of the /var/cfengine/cache/cfsec_shadow file every time the
/etc/passwd file is modified is a little inefficient, and I will probably
modify that to just update the fields that are different but this is working
for now.
Any suggestions/criticisms or otherwise are welcome and greatly appreciated.
_______________________________________________
Help-cfengine mailing list
[email protected]
https://cfengine.org/mailman/listinfo/help-cfengine