Skip to content

Commit

Permalink
laps-runner-pam script to avoid blocking PAM logout flow; PAM_SERVICE…
Browse files Browse the repository at this point in the history
… filter in config file instead of parameter
  • Loading branch information
schorschii committed Nov 28, 2024
1 parent 2ed0368 commit 2c0bd50
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 11 deletions.
1 change: 1 addition & 0 deletions installer/deb/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ fi
# copy files in place
install -D -m 644 ../../README.md -t $BUILDDIR/$INSTALLDIR
install -D -m 755 ../../assets/laps-runner.cron $BUILDDIR/etc/cron.hourly/laps-runner
install -D -m 755 ../../laps-runner/laps-runner-pam -t $BUILDDIR/usr/sbin
install -D -m 644 ../../laps-runner/laps_runner/*.py -t $BUILDDIR/$INSTALLDIR/laps_runner
install -D -m 644 ../../laps-runner/requirements.txt -t $BUILDDIR/$INSTALLDIR
install -D -m 644 ../../laps-runner/setup.py -t $BUILDDIR/$INSTALLDIR
Expand Down
1 change: 1 addition & 0 deletions installer/rpm/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ cp ../../README.md laps4linux-client-$VERSION/usr/share/laps4
cp ../../assets/LAPS4LINUX.desktop laps4linux-client-$VERSION/usr/share/applications
cp ../../assets/laps.png laps4linux-client-$VERSION/usr/share/pixmaps
cp ../../assets/laps-runner.cron laps4linux-runner-$VERSION/etc/cron.hourly/laps-runner
cp ../../laps-runner/laps-runner-pam laps4linux-runner-$VERSION/usr/sbin/laps-runner-pam
cp ../../laps-runner/laps_runner/*.py laps4linux-runner-$VERSION/usr/share/laps4linux-runner/laps_runner
cp ../../laps-runner/requirements.txt laps4linux-runner-$VERSION/usr/share/laps4linux-runner
cp ../../laps-runner/setup.py laps4linux-runner-$VERSION/usr/share/laps4linux-runner
Expand Down
3 changes: 3 additions & 0 deletions installer/rpm/rpmbuild/SPECS/laps4linux-runner.spec
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}
cp etc/laps-runner.json $RPM_BUILD_ROOT/%{_sysconfdir}
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/cron.hourly/
cp etc/cron.hourly/laps-runner $RPM_BUILD_ROOT/%{_sysconfdir}/cron.hourly/
mkdir -p $RPM_BUILD_ROOT/%{_sbindir}
cp usr/sbin/laps-runner-pam $RPM_BUILD_ROOT/%{_sbindir}/laps-runner-pam

%post
DIR=/usr/share/laps4linux-runner
Expand All @@ -46,6 +48,7 @@ rm -rf $RPM_BUILD_ROOT

%files
%{_sbindir}/laps-runner
%{_sbindir}/laps-runner-pam
%{_sysconfdir}/laps-runner.json
%{_sysconfdir}/cron.hourly/laps-runner
/usr/share/laps4linux-runner/laps_runner/filetime.py
Expand Down
6 changes: 4 additions & 2 deletions laps-runner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ Priority: 0
Session-Type: Additional
Session-Interactive-Only: yes
Session:
optional pam_exec.so type=close_session seteuid quiet /usr/sbin/laps-runner --pam
optional pam_exec.so type=close_session seteuid quiet /usr/sbin/laps-runner-pam
```
Use `Session-Interactive-Only: no` if you like to rotate the password on sudo usage too. You can add the parameter `--pam-service login` if you do not want to change the password on `sudo -i` usage. The `--pam-service` parameter can be used multiple times - this allows you to trigger LAPS on multiple, specific PAM service events.
Use `Session-Interactive-Only: no` if you like to rotate the password on sudo usage too.

Then, run `pam-auth-update` to automatically generate the files under `/etc/pam.d/` with the necessary line for LAPS.

You can add `login` to the array `pam-services` in the config file if you do not want to change the password on `sudo -i` usage. Since this config option is an array, this allows you to trigger LAPS on multiple, specific PAM service events.

If you want the runner to wait a certain time after logout until the password should be changed, set `pam-grace-period` in the runner config to the desired number of seconds, e.g. 300 for 5 minutes.

### Hostnames Longer Than 15 Characters
Expand Down
3 changes: 3 additions & 0 deletions laps-runner/laps-runner-pam
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

nohup /usr/sbin/laps-runner --pam &
3 changes: 2 additions & 1 deletion laps-runner/laps-runner.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@
"password-length": 15,
"password-alphabet": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",

"pam-grace-period": 0
"pam-services-EXAMPLE": ["login"],
"pam-grace-period-EXAMPLE": 300
}
18 changes: 10 additions & 8 deletions laps-runner/laps_runner/laps_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ class LapsRunner():
cfgHostname = None
cfgUsername = 'root' # the user, whose password should be changed
cfgDaysValid = 30 # how long the new password should be valid
cfgPamGracePeriod = 0 # timeout in seconds to wait before changing the password after logout (PAM mode)
cfgLength = 15 # the generated password length
cfgAlphabet = string.ascii_letters+string.digits+string.punctuation # allowed chars for the new password

Expand All @@ -56,6 +55,9 @@ class LapsRunner():
cfgLdapAttributePasswordHistory = 'msLAPS-EncryptedPasswordHistory'
cfgLdapAttributePasswordExpiry = 'msLAPS-PasswordExpirationTime'

cfgPamServices = [] # PAM_SERVICE filter
cfgPamGracePeriod = 0 # timeout in seconds to wait before changing the password after logout

tmpDn = ''
tmpPassword = None
tmpExpiry = ''
Expand Down Expand Up @@ -312,7 +314,8 @@ def LoadSettings(self):
self.cfgLdapAttributePasswordHistory = str(cfgJson.get('ldap-attribute-password-history', self.cfgLdapAttributePasswordHistory))
self.cfgLdapAttributePasswordExpiry = str(cfgJson.get('ldap-attribute-password-expiry', self.cfgLdapAttributePasswordExpiry))
self.cfgHostname = cfgJson.get('hostname', self.cfgHostname)
self.cfgPamGracePeriod = cfgJson.get('pam-grace-period', self.cfgPamGracePeriod)
self.cfgPamServices = cfgJson.get('pam-services', self.cfgPamServices)
self.cfgPamGracePeriod = int(cfgJson.get('pam-grace-period', self.cfgPamGracePeriod))

def main():
runner = LapsRunner()
Expand All @@ -321,7 +324,6 @@ def main():
parser = argparse.ArgumentParser(epilog=__copyright__+' '+__author__+' - https://georg-sieber.de')
parser.add_argument('-f', '--force', action='store_true', help='Force updating password, even if it is not expired')
parser.add_argument('-p', '--pam', action='store_true', help='PAM mode - update password if configured user has logged out, even if it is not expired')
parser.add_argument('-s', '--pam-service', default=None, nargs='+', help='Only change password in PAM mode if PAM_SERVICE matches the given value (e.g. "login" or "sudo-i")')
parser.add_argument('-c', '--config', default=runner.cfgPath, help='Path to config file ['+str(runner.cfgPath)+']')
args = parser.parse_args()
if args.config: runner.cfgPath = args.config
Expand All @@ -343,18 +345,18 @@ def main():
runner.updatePassword()

elif args.pam:
if 'PAM_TYPE' not in os.environ or 'PAM_USER' not in os.environ:
raise Exception('PAM_TYPE or PAM_USER missing!')
if args.pam_service and os.environ['PAM_SERVICE'] not in args.pam_service:
runner.logger.debug(__title__+': PAM_SERVICE "'+os.environ['PAM_SERVICE']+'" is not one of '+str(args.pam_service)+', exiting.')
if 'PAM_SERVICE' not in os.environ or 'PAM_USER' not in os.environ:
raise Exception('PAM_SERVICE or PAM_USER missing!')
if runner.cfgPamServices and os.environ['PAM_SERVICE'] not in runner.cfgPamServices:
runner.logger.debug(__title__+': PAM_SERVICE "'+os.environ['PAM_SERVICE']+'" is not one of '+str(runner.cfgPamServices)+', exiting.')
sys.exit(0)
if os.environ['PAM_USER'] != runner.cfgUsername:
runner.logger.debug(__title__+': PAM_USER does not match the configured user, exiting.')
sys.exit(0)
if runner.cfgPamGracePeriod:
runner.logger.debug(__title__+': PAM timeout - waiting '+str(runner.cfgPamGracePeriod)+' seconds...')
time.sleep(runner.cfgPamGracePeriod)
print('Updating password (forced update by PAM logout)...')
print('Updating password (forced update by PAM)...')
runner.updatePassword()

else:
Expand Down

0 comments on commit 2c0bd50

Please sign in to comment.