Update for automated response around poorly behaving archlinux-keyring weekly timer; rename Sora role to Password

This commit is contained in:
DarkFeather 2024-03-07 12:27:21 -06:00
parent 930441ae9a
commit e75d03a313
Signed by: DarkFeather
GPG Key ID: 1CC1E3F4ED06F296
29 changed files with 360 additions and 64 deletions

View File

@ -2,7 +2,9 @@ This project is our Infrastructure-as-Code solution, detailing the deployment &
# Etymology # Etymology
It is named after the fictional Star Wars Imperial Intelligence organization that oversaw the various divisions of Intelligence and orchestrated their operations. Like its namesake, this project oversees the various tools within our ecosystem and enforces compliance with standards. It is named after flagship carrier Kapisi from the game [Homeworld: Deserts of Kharak](https://store.steampowered.com/app/281610?snr=5000_5100___primarylinks). The carrier was the command and production center of Operation Khadiim, an expedition to understand an anomaly on their world & escape the fanaticism of their Gaalsien rivals. The S'jet were able to succeed in this mission not only due to the military efficacy of their forces but also through the research and production capabilities available to the Kapisi.
This project seeks to give other admins and engineers to launch their own infrastructures and break out of any strangleholds that may have entangled them, whether that is tribalism, vendor lock, or stigma.
# Relevant Files and Software # Relevant Files and Software
@ -12,7 +14,7 @@ export ANSIBLE_VAULT_PASSWORD_FILE=$HOME/password-store/${organization}.vault.pa
export ANSIBLE_VAULT_FILE=$HOME/password-store/${organization}.vault export ANSIBLE_VAULT_FILE=$HOME/password-store/${organization}.vault
``` ```
Take a look at `examples/msn0.yml` as an example inventory -- make sure you populate one of your own. Take a look at `examples/msn0.yml` as an example inventory -- make sure you populate one of your own. The scripts here expect inventories to have layers of groups -- the top group under `all` must be managed vs. unmanaged. The rest of the scripts use YAMLPath to sort out the rest of the groups.
Once you have your vault and inventory, use [AniNIX/ShadowArch](/AniNIX/ShadowArch) with your hypervisor to provision the base image for your machines, or [Raspbian](https://www.raspberrypi.org/). Once you have your vault and inventory, use [AniNIX/ShadowArch](/AniNIX/ShadowArch) with your hypervisor to provision the base image for your machines, or [Raspbian](https://www.raspberrypi.org/).

View File

@ -0,0 +1,3 @@
#!/bin/bash
slapcat -a "(!(entryDN:dnSubtreeMatch:=ou=People,dc=aninix,dc=net))"

View File

@ -0,0 +1,119 @@
dn: dc=aninix,dc=net
objectClass: dcObject
objectClass: organization
dc: aninix
o: AniNIXUsers
description: AniNIX::LDAP Crediential Directory
structuralObjectClass: organization
entryUUID: a521b05a-3532-4042-bf8f-3631a1e51b94
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20160901205333Z
entryCSN: 20160901205333.449191Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20160901205333Z
dn: cn=root,dc=aninix,dc=net
objectClass: organizationalRole
cn: root
description: Directory Manager
structuralObjectClass: organizationalRole
entryUUID: 9e4273d9-d002-4015-a774-bed02afd6cc9
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20160901205333Z
pwdLastSuccess: 20220918222625Z
entryCSN: 20220918222625.132392Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20220918222625Z
dn: ou=Group,dc=aninix,dc=net
ou: Group
objectClass: top
objectClass: organizationalUnit
structuralObjectClass: organizationalUnit
entryUUID: 475e1ae1-d992-4a9a-85de-e7f71974ac03
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20160901214257Z
entryCSN: 20160901214257.941445Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20160901214257Z
dn: cn=ldapuser,ou=Group,dc=aninix,dc=net
cn: ldapuser
gidNumber: 10000
objectClass: posixGroup
objectClass: top
structuralObjectClass: posixGroup
entryUUID: dc17d42d-fae9-496d-b362-82f27679476c
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20160903051753Z
entryCSN: 20160903051753.156600Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20160903051753Z
dn: cn=hypervisorauth,ou=Group,dc=aninix,dc=net
cn: hypervisorauth
gidNumber: 10001
objectClass: posixGroup
objectClass: top
structuralObjectClass: posixGroup
entryUUID: 88cb5e2c-ee93-4d62-a83a-63ceff9ceba0
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20160903061147Z
memberUid: lurso3
entryCSN: 20160903061653.689826Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20160903061653Z
dn: ou=pwpolicies,dc=aninix,dc=net
ou: pwpolicies
objectClass: top
objectClass: organizationalUnit
structuralObjectClass: organizationalUnit
entryUUID: ee2c6fc6-a40a-4d6f-992e-c1a04439f022
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20161029155416Z
entryCSN: 20161029155416.247439Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20161029155416Z
dn: cn=default,ou=pwpolicies,dc=aninix,dc=net
objectClass: pwdPolicy
objectClass: person
objectClass: top
cn: default
sn: Default
pwdAttribute: userPassword
pwdMaxAge: 31536000
pwdExpireWarning: 604800
pwdInHistory: 12
pwdCheckQuality: 1
pwdMaxFailure: 5
pwdLockout: TRUE
pwdLockoutDuration: 86400
pwdGraceAuthNLimit: 3
pwdFailureCountInterval: 3600
pwdMustChange: TRUE
pwdMinLength: 8
pwdAllowUserChange: TRUE
pwdSafeModify: FALSE
structuralObjectClass: person
entryUUID: f983ea45-deca-4b8f-8e55-cebbacf392ba
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20161029171109Z
entryCSN: 20161029171109.930559Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20161029171109Z
dn: cn=DarkFeather,ou=Group,dc=aninix,dc=net
cn: DarkFeather
gidNumber: 10002
objectClass: posixGroup
objectClass: top
memberUid: DarkFeather
structuralObjectClass: posixGroup
entryUUID: 1f333fb2-0611-4235-ba07-aa9fa0edb439
creatorsName: cn=root,dc=aninix,dc=net
createTimestamp: 20201018201805Z
entryCSN: 20201018201805.104347Z#000000#000#000000
modifiersName: cn=root,dc=aninix,dc=net
modifyTimestamp: 20201018201805Z

View File

@ -0,0 +1,26 @@
binlist = ldap-adduser ldap-userreport ldap-resetpass
filelist = sample-user.ldif
compile:
@echo Nothing to do
install: clean ${binlist} ${filelist}
mkdir -p ${pkgdir}/opt/aninix/Password/
for i in ${filelist}; do install -m 0640 -o ldap -g ldap $$i ${pkgdir}/opt/aninix/Password/; done
mkdir -p ${pkgdir}/usr/local/sbin/
for i in ${binlist}; do install -m 0750 -o root -g root $$i ${pkgdir}/usr/local/sbin; done
test: compile
@echo Nothing to do
clean:
@echo Nothing to do.
diff:
@echo Nothing to do.
reverse:
@echo Nothing to do.
checkperm:
@echo Nothing to do.

View File

@ -0,0 +1,46 @@
depends=('bash>=4.4' 'openldap')
makedepends=('make>=4.2')
checkdepends=()
optdepends=()
pkgname="Password-Scripts"
pkgver="$(git describe --tag --abbrev=0)"."$(git rev-parse --short HEAD)"
pkgrel=1
pkgrel() {
echo $(( `git log "$(git describe --tag --abbrev=0)"..HEAD | grep -c commit` + 1 ))
}
epoch="$(git log | grep -c commit)"
pkgdesc="AniNIX/Password Scripts"
arch=("x86_64")
url="$(git config remote.origin.url | sed 's/.git$//')"
license=('custom')
groups=()
provides=("${pkgname}")
conflicts=()
replaces=("${pkgname,,}" "aninix-${pkgname,,}")
backup=()
options=()
install=
changelog=
source=()
noextract=()
md5sums=()
validpgpkeys=()
prepare() {
git pull || true
}
build() {
make -C ..
}
check() {
chmod -R u+r ../pkg
make -C .. test
}
package() {
export pkgdir="${pkgdir}"
make -C .. install
install -D -m644 ../../../../LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
}

View File

@ -43,16 +43,15 @@ if [ "$?" -eq 0 ]; then
read answer read answer
if [ "$answer" == "YES" ]; then if [ "$answer" == "YES" ]; then
file="/etc/openldap/users.d/$username.ldif" file="/etc/openldap/users.d/$username.ldif"
cp /usr/local/src/ConfigPackages/Sora/sample-user.ldif "$file" cp /opt/aninix/Password/sample-user.ldif "$file"
line="$(grep -E '^uid: ' "$file")"; sed -i "s/$line/uid: $username/" "$file" line="$(grep -E '^uid: ' "$file")"; sed -i "s/$line/uid: $username/" "$file"
line="$(grep -E '^dn: ' "$file" | cut -f 2 -d ' ' | cut -f 1 -d ',')"; sed -i "s/$line/uid=$username/" "$file" line="$(grep -E '^dn: ' "$file" | cut -f 2 -d ' ' | cut -f 1 -d ',')"; sed -i "s/$line/uid=$username/" "$file"
line="$(grep -E '^homeDirectory: ' "$file")"; sed -i "s#$line#homeDirectory: /home/$username/#" "$file" line="$(grep -E '^homeDirectory: ' "$file")"; sed -i "s#$line#homeDirectory: /home/$username/#" "$file"
line="$(grep -E '^cn: ' "$file")"; sed -i "s/$line/cn: $username/" "$file" line="$(grep -E '^cn: ' "$file")"; sed -i "s/$line/cn: $username/" "$file"
line="$(grep -E '^mail: ' "$file")"; sed -i "s#$line#mail: ircs://aninix.net:6697/$username#" "$file" line="$(grep -E '^mail: ' "$file")"; sed -i "s#$line#mail: ircs://aninix.net:6697/$username#" "$file"
line="$(grep -E '^uidNumber: ' "$file")"; sed -i "s/$line/uidNumber: $newuserid/" "$file" line="$(grep -E '^uidNumber: ' "$file")"; sed -i "s/$line/uidNumber: $newuserid/" "$file"
ldapadd -D 'cn=root,dc=aninix,dc=net' -y /root/.ldappass -f "$file" ldapadd -D 'cn=root,dc=aninix,dc=net' -W -f "$file"
ldap-resetpass "$username" ldap-resetpass "$username"
# usermod -a -G ssh-allow,passwdchange "$username"
fi fi
rmdir "$lockfile" rmdir "$lockfile"
exit 0; exit 0;

View File

@ -7,11 +7,11 @@ if [ -z "$uid" ]; then
exit 1 exit 1
fi fi
ldappasswd -D 'cn=root,dc=aninix,dc=net' -y /root/.ldappass "uid=$uid,ou=People,dc=aninix,dc=net" ldappasswd -D 'cn=root,dc=aninix,dc=net' -W "uid=$uid,ou=People,dc=aninix,dc=net"
if [ `ldapsearch -x "(uid=$uid)" + \* | grep -c shadowLastChange\:` -ne 0 ]; then if [ `ldapsearch -x "(uid=$uid)" + \* | grep -c shadowLastChange\:` -ne 0 ]; then
(printf "dn: uid=$uid,ou=People,dc=aninix,dc=net\nchangetype: modify\ndelete: shadowLastChange\n\n") | ldapmodify -D 'cn=root,dc=aninix,dc=net' -y /root/.ldappass &>/dev/null; (printf "dn: uid=$uid,ou=People,dc=aninix,dc=net\nchangetype: modify\ndelete: shadowLastChange\n\n") | ldapmodify -D 'cn=root,dc=aninix,dc=net' -W &>/dev/null;
fi fi
(printf "dn: uid=$uid,ou=People,dc=aninix,dc=net\nchangetype: modify\nadd: shadowLastChange\nshadowLastChange: 0\n\ndn: uid=$uid,ou=People,dc=aninix,dc=net\nchangetype: modify\nadd: pwdReset\npwdReset: TRUE\n\n") | ldapmodify -D 'cn=root,dc=aninix,dc=net' -y /root/.ldappass &>/dev/null; (printf "dn: uid=$uid,ou=People,dc=aninix,dc=net\nchangetype: modify\nadd: shadowLastChange\nshadowLastChange: 0\n\ndn: uid=$uid,ou=People,dc=aninix,dc=net\nchangetype: modify\nadd: pwdReset\npwdReset: TRUE\n\n") | ldapmodify -D 'cn=root,dc=aninix,dc=net' -W &>/dev/null;
exit $? exit $?

View File

@ -8,17 +8,9 @@ function shortshow() {
echo ${user}": "$email echo ${user}": "$email
} }
function queryLDAPAttribute() {
ldapsearch -x "$1" "$2" | grep -E "${2}: " | sed "s/^${2}: //"
}
basedn=`ldapsearch -x '(cn=root)' dn | grep -E ^dn:\ | sed 's/dn: cn=root,//'` basedn=`ldapsearch -x '(cn=root)' dn | grep -E ^dn:\ | sed 's/dn: cn=root,//'`
maxAge="$(queryLDAPAttribute '(cn=default)' pwdMaxAge)" for user in `ldapsearch -x -b "ou=People,$basedn" '(uid=*)' uid | grep -E ^uid:\ | sed 's/^uid: //'`; do
changeAge=$(( $maxAge - 2592000 ))
deleteAge=$(( 2 * $maxAge ))
for user in `queryLDAPAttribute '(uid=*)' uid`; do
# Pull changed stats # Pull changed stats
lastChanged=`/usr/sbin/ldapsearch -x "(uid=$user)" + | grep pwdChangedTime | cut -f 2 -d ' '` lastChanged=`/usr/sbin/ldapsearch -x "(uid=$user)" + | grep pwdChangedTime | cut -f 2 -d ' '`
@ -45,7 +37,7 @@ for user in `queryLDAPAttribute '(uid=*)' uid`; do
if [ "$lastChanged" == "$errortext" ]; then if [ "$lastChanged" == "$errortext" ]; then
shortshow shortshow
else else
if [ $delta -gt "$changeAge" ] && [ $delta -lt "$maxAge" ]; then shortshow; fi if [ $delta -gt 28512000 ] && [ $delta -lt 31536000 ]; then shortshow; fi
fi fi
;; ;;
"--expired") "--expired")
@ -53,11 +45,6 @@ for user in `queryLDAPAttribute '(uid=*)' uid`; do
shortshow; shortshow;
fi fi
;; ;;
"--removeable")
if [ "$lastChanged" != "$errortext" ] && [ "$delta" -ge "$deleteAge" ]; then
shortshow;
fi
;;
*) *)
cat cat
;; ;;

View File

@ -0,0 +1,21 @@
dn: uid=testuser,ou=People,dc=aninix,dc=net
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: testuser
cn: Test User
sn: User
givenName: Test
title: User
telephoneNumber: +0 000 000 0000
mobile: +0 000 000 0000
postalAddress: AddressLine1$AddressLine2$AddressLine3
loginShell: /bin/bash
uidNumber: 10006
gidNumber: 10000
homeDirectory: /home/testuser
description: Work contact
mail: testuser@aninix.net

View File

@ -0,0 +1,35 @@
---
- name: Create the base config
become: yes
template:
src: slapd.ldif
dest: /etc/openldap/slapd.ldif
owner: ldap
group: ldap
mode: 0640
- name: Create the directories
file:
path: "{{ item }}"
owner: ldap
group: ldap
mode: 0700
loop:
- /var/lib/openldap/openldap-data/
- /etc/openldap
- /etc/openldap/users.d
- /etc/openldap/groups.d
- /etc/openldap/slapd.d
- name: Initialize the instance
become: yes
command:
cmd: slapadd -n 0 -F /etc/openldap/slapd.d/ -l /etc/openldap/config.ldif && chown -R ldap: /etc/openldap
creates: /etc/openldap/slapd.d/cn=config
- name: Ensure the service
become: yes
service:
name: slapd
state: restarted
enabled: yes

View File

@ -0,0 +1,17 @@
---
- name: Set login config
become: yes
template:
src: nslcd.conf.j2
dest: /etc/nslcd.conf
owner: nslcd
group: nslcd
mode: 0600
- name: Ensure login service
become: yes
service:
name: nslcd
state: restarted
enabled: yes

View File

@ -0,0 +1,13 @@
---
- name: Sora packages
become: yes
package:
name:
- openldap
- Password-Scripts
- include_tasks: daemon.yml
- include_tasks: login.yml
- include_tasks: web.yml

View File

@ -0,0 +1,24 @@
---
- name: Clone the web portal
become: yes
git:
repo: https://github.com/ltb-project/self-service-password
dest: /usr/share/webapps/self-service-password
- name: Ensure web portal ownership
file:
state: directory
owner: http
group: http
path: /usr/share/webapps/self-service-password
recurse: true
- name: Web portal config
become: yes
template:
src: config.inc.php.j2
dest: /usr/share/webapps/self-service-password/conf/config.inc.php
owner: http
group: http
mode: 0600

View File

@ -0,0 +1,3 @@
check program check_archlinux_wkd with path "/usr/bin/systemctl is-failed archlinux-keyring-wkd-sync.service"
if status == 0 for 1 times within 5 cycles then exec "/usr/bin/systemctl reset-failed archlinux-keyring-wkd-sync.service"
if status == 0 for 5 times within 5 cycles then exec "/etc/monit.d/scripts/critical CRITICAL: Archlinux Keyring WKD Sync has failed and automated remediation has not solved it."

View File

@ -1 +1,2 @@
include "/etc/monit.d/checks/system" include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/automated_response"

View File

@ -1 +1,2 @@
include "/etc/monit.d/checks/system" include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/automated_response"

View File

@ -0,0 +1 @@
include "/etc/monit.d/checks/system"

View File

@ -0,0 +1 @@
include "/etc/monit.d/checks/system"

View File

@ -0,0 +1 @@
include "/etc/monit.d/checks/system"

View File

@ -0,0 +1 @@
include "/etc/monit.d/checks/system"

View File

@ -0,0 +1 @@
include "/etc/monit.d/checks/system"

View File

@ -1,3 +1,4 @@
include "/etc/monit.d/checks/system" include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/vips" include "/etc/monit.d/checks/vips"
include "/etc/monit.d/checks/availability" include "/etc/monit.d/checks/availability"
include "/etc/monit.d/checks/automated_response"

View File

@ -2,3 +2,4 @@ include "/etc/monit.d/checks/system"
include "/etc/monit.d/checks/watcher-of-watchers" include "/etc/monit.d/checks/watcher-of-watchers"
include "/etc/monit.d/checks/warrant-canary" include "/etc/monit.d/checks/warrant-canary"
include "/etc/monit.d/checks/grimoire" include "/etc/monit.d/checks/grimoire"
include "/etc/monit.d/checks/automated_response"

View File

@ -33,33 +33,17 @@
- sharingan-scan.service - sharingan-scan.service
- sharingan-scan.timer - sharingan-scan.timer
- name: Scanning services
become: yes
register: clam_svc
copy:
src: "clamav/{{ item }}"
dest: /usr/lib/systemd/system/
owner: root
group: root
mode: 0664
loop:
- freshclam.service
- freshclam.timer
- clamscan.service
- clamscan.timer
- systemd: - systemd:
daemon_reload: yes daemon_reload: yes
become: yes become: yes
when: clam_svc.changed or lynis_svc.changed when: lynis_svc.changed
- name: Enable timers - name: Enable timers
become: yes become: yes
loop:
- freshclam.timer
- sharingan-scan.timer
service: service:
name: "{{ item }}" name: sharingan-scan.timer
state: restarted state: restarted
enabled: yes enabled: yes
- import_tasks: "./vscan.yml"
when: vscan_enabled is defined

View File

@ -5,7 +5,8 @@
package: package:
name: name:
- elasticsearch - elasticsearch
- mongodb44-bin # Temporarily pinned for extensions - mongodb-bin
- mongodb-tools-bin
- graylog - graylog
state: present state: present

View File

@ -0,0 +1,26 @@
---
- name: Virus scanning services
become: yes
register: clam_svc
copy:
src: "clamav/{{ item }}"
dest: /usr/lib/systemd/system/
owner: root
group: root
mode: 0664
loop:
- freshclam.service
- freshclam.timer
- clamscan.service
- clamscan.timer
- name: Enable timers
become: yes
loop:
- freshclam.timer
- clamscan.timer
service:
name: "{{ item }}"
state: restarted
enabled: yes

View File

@ -1,7 +0,0 @@
---
- name: Sora packages
become: yes
package:
name:
- openldap

View File

@ -1,12 +0,0 @@
---
- command: ./scripts/generate-dhcp.py
delegate_to: localhost
run_once: true
name: Generate DHCP leases.
- command: ./scripts/generate-dns.py
delegate_to: localhost
run_once: true
name: Generate DNS entries