Forum Discussion

PerBonomi's avatar
5 years ago

Remove sensitive roles from inactive users

Saw this idea and couldn't remember if I shared this already.

Basically an endpoint that gets called every day and

  • Loops through a list of roles
  • Finds users with those roles
  • Checks that they're not special accounts, e.g. API user accounts
  • Removes the sensitive roles
  • Per affected user it lists the roles that were removed and the roles that remain
  • Optionally sends a PM to the user to notify them

Comments inline.

I use Google Apps Script to schedule a daily run, but of course there are other options.

Disclaimer: I'm not a trained programmer

<#-- Automatically remove roles with permissions from users who haven't logged in for a while -->
<#assign user_limit = http.request.parameters.name.get("user_limit", "100")?string />
<#-- How many days must the user have been inactive -->
<#assign days_staff = http.request.parameters.name.get("", "50")?number />
<#assign days_mod = http.request.parameters.name.get("", "30")?number />
<#assign send_pm = http.request.parameters.name.get("pm", "false")?boolean />
<#-- Roles to remove from the users we find -->
	<#assign user_roles_remove = [
		"Administrator",
		"LSI",
		"Level Two Moderator",
		"Lithium",
		"Moderator"
	]/>
	<#-- Some users, like API accounts should be skipped, these are their IDs -->
		<#assign staff_exceptions = [
			123,
			456,
			789
		]/>
	</#if>
	<#assign users_pm_ids = []/> <#-- Spinning up a sequnce to store the IDs of users we may want to PM about their removed access -->
	<#assign today_long = .now?date?long/>
	<#assign prev_long_staff = today_long - days_staff * 1000 * 60 * 60 * 24/>
	<#assign prev_long_mod = today_long - days_mod * 1000 * 60 * 60 * 24/>

	<#-- convert the user's last visit date string to the long format for calculation -->
	<#function fnLVD(lvd)>
		<#assign lvd_show = lvd?datetime?string["yyyy-MM-dd"]/>
		<#assign lvd_long = lvd?datetime?long/>
		<#return lvd_long/>
	</#function>

	<xml>
		<users>
			<#-- Mods -->
			<#assign query_mod = restadmin("2.0","/search?q=" + "SELECT id,login,last_visit_time FROM users WHERE roles.name IN('Moderator','Level Two Moderator') LIMIT ${user_limit}"?url)/>
			<#list query_mod.data.items?sort_by("last_visit_time") as u>
				<#assign lvd_long = fnLVD(u.last_visit_time)/>
				<#if (lvd_long < prev_long_mod)>
					<#assign user_id = u.id/>
					<#assign user_login = u.login/>
					<#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/>
					<#assign user_roles_before = []/>
					<#list query_user_roles.data.items as r>
						<#assign role_name = r.name/>
						<#assign user_roles_before = user_roles_before + [role_name]/>
					</#list>
					<#list user_roles_remove as r>
						<#if (user_roles_before?seq_index_of(r) >= 0)>
							<#assign result = restadmin("/roles/name/" + r?url + "/users/remove?role.user=id/" + user_id)/>
						</#if>
					</#list>
					<#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/>
					<#assign user_roles_after = []/>
					<#list query_user_roles.data.items as r>
						<#assign role_name = r.name/>
						<#assign user_roles_after = user_roles_after + [role_name]/>
					</#list>
					<user>
						<login>${user_login}</login>
						<id>${user_id}</id>
						<user_type>Moderator</user_type>
						<roles_removed>
							<#list user_roles_before as r>
								<#if (user_roles_after?seq_index_of(r) < 0) && user_roles_remove?seq_index_of(r) >= 0)>
									<#if (users_pm_ids?seq_index_of(user_id) < 0)>
										<#assign users_pm_ids = users_pm_ids + [user_id]/>
									</#if>
									<role_name>${r}</role_name>
								</#if>
							</#list>
						</roles_removed>
						<roles_not_removed>
							<#list roles_remove as r>
								<#if (user_roles_after?seq_index_of(r) >= 0)>
									<role_name>${r}</role_name>
								</#if>
							</#list>
						</roles_not_removed>
					</user>
				</#if>
			</#list>
			<#--  -->
			<#-- Staff -->
			<#assign staff_users = []/>
			<#assign query_staff = restadmin("2.0","/search?q=" + "SELECT id,login,last_visit_time FROM users WHERE roles.name IN('Staff','Administrator','LSI','Lithium') LIMIT ${user_limit}"?url)/>
			<#list query_staff.data.items?sort_by("last_visit_time") as u>
				<#assign lvd_long = fnLVD(u.last_visit_time)/>
				<#if (lvd_long < prev_long_mod)>
					<#assign user_id = u.id/>
					<#assign user_login = u.login/>
					<#assign user_exception = false/>
					<#list staff_exceptions as s>
						<#if s?number == user_id?number>
							<#assign user_exception = true/>
							<#break>
						</#if>			
					</#list>
					<#if user_exception == false>
						<#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/>
						<#assign user_roles_before = []/>
						<#list query_user_roles.data.items as r>
							<#assign role_name = r.name/>
							<#assign user_roles_before = user_roles_before + [role_name]/>
						</#list>
						<#if (user_roles_before?seq_index_of("Staff") >= 0)>
							<#assign staff_users = staff_users + [user_id]/>
						</#if>
						<#list user_roles_remove as r>
							<#if (user_roles_before?seq_index_of(r) >= 0)>
								<#assign result = restadmin("/roles/name/" + r?url + "/users/remove?role.user=id/" + user_id)/>
							</#if>
						</#list>
						<#assign query_user_roles = restadmin("2.0","/search?q=" + "SELECT name FROM roles WHERE users.id = '${user_id}' LIMIT 500"?url)/>
						<#assign user_roles_after = []/>
						<#list query_user_roles.data.items as r>
							<#assign role_name = r.name/>
							<#assign user_roles_after = user_roles_after + [role_name]/>
						</#list>
						<user>
							<login>${user_login}</login>
							<id>${user_id}</id>
							<user_type>Admin,Staff</user_type>
							<roles_removed>
								<#list user_roles_before as r>
									<#if (user_roles_after?seq_index_of(r) < 0) && (user_roles_remove?seq_index_of(r) >= 0)>
										<#if (users_pm_ids?seq_index_of(user_id) < 0)>
											<#assign users_pm_ids = users_pm_ids + [user_id]/>
										</#if>
										<role_name>${r}</role_name>
									</#if>
								</#list>
							</roles_removed>
							<roles_not_removed>
								<#list user_roles_remove as r>
									<#if (user_roles_after?seq_index_of(r) >= 0)>
										<role_name>${r}</role_name>
									</#if>
								</#list>
							</roles_not_removed>
						</user>				
					</#if>
				</#if>
			</#list>
		</users>
	</xml>
	<#if send_pm == true>
		<#assign pm_subject = "Your access has been removed"?url/>
		<#assign pm_body = "<p>Hey! Due to inactivity we have removed some of the more sensitive access from your account.</p><p>If you feel this was in error, please contact the Community Team.</p><p style='margin:40px 0; color:#bbb;font-size:10px'>Please do not reply to this message</p>"?url/>
		<#list users_pm_ids as u>
			<#assign result_send = restadmin("/postoffice/notes/send?notes.recipient=/users/id/" + u + "&notes.subject=" + pm_subject + "&notes.note=test")/>
		</#list>
	</#if>
</#if>

 

No RepliesBe the first to reply