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 Help-cfengine@cfengine.org https://cfengine.org/mailman/listinfo/help-cfengine