PerBonomi
5 years agoBoss
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 + "¬es.subject=" + pm_subject + "¬es.note=test")/>
</#list>
</#if>
</#if>