Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Link to github sources

...

Excerpt

To save on licensing costs, it is sometimes useful to automatically deactivate Jira users who haven't logged in within a certain period, say 6 months. Here we review the options, and provide a ScriptRunner script (source in github) that does the job.


Table of Contents

...

  1. "User has not logged in in X months" is a good start.
  2. How about users that have never logged in? It depends on the age of their user account: if it was created yesterday, but they haven't logged in yet, leave the account alone; if it was created last year and they haven't logged in, it should be deactivated. So let's also deactivate users whose account was created more than X months ago, AND who have never logged in.

    Note
    iconfalse

    Incidentally, if you do a web search for Jira deactivate inactive users' you will see many solutions, like this ScriptRunner script from Adaptavist, that don't handle this edge case (probably because Jira's regular API doesn't expose the 'created' date).


  3. Jira instances often have multiple directories. It's not possible to deactivate users in LDAP / AD User Directories, so let's add the criteria: users are in the internal (id 1) or Crowd directory (e.g. id 10000)
  4. Does your Jira have an 'admin' role account on the Internal directory, only used in emergencies when the external user provider (Crowd, LDAP, external Jira) is offline? This shouldn't be automatically deactivated. We must add the rule exclude emergency access accounts.
  5. Does your Jira contain any 'role' accounts never log in, but are still valid? Perhaps a role account like 'qa' that is assigned issues so that qa@mycompany.com gets notified? If so, we need a exclude role accounts that are used but never log in rule to prevent these role accounts getting deactivated.

...

Our first generic solution is a ScriptRunner for Jira Groovy script. It deactivates users matching rules 1, 2 and 3, namely users in the Internal Directory (1) who have not logged in X months, or who have never logged in to an account created more than X months ago.

Include Code
languagegroovy
urlhttps://raw.githubusercontent.com/redradishtech/jira-user-deactivator-groovy/master/deactivate-inactive-jira-users-nonsql.groovy

To put use this script into productionto automatically deactivate users:

  • Save

    Checkout the

    above

    script from the github repository to $JIRAHOME/scripts:

    Code Block
    cd $JIRAHOME/scripts
    git clone https://github.com/redradishtech/
    deactivate_inactive_users.groovy. Make it owned by root but readable by group jira.
    jira-user-deactivator-groovy
    chgrp -R jira jira-user-deactivator-groovy    # Ensure Jira has read access.


  • If you first want to see what would  happen without deactivating anyone, edit deactivate-inactive-jira-users-nonsql.groovy  and comment out the updateUser line:

    Code Block
    // Comment out this line to do a dry run:
    // userService.updateUser(updateUserValidationResult)


  • Go to the ScriptRunner Jobs tab, e.g. by typing 'gg' then 'Script jobs':

    Image Added
    (ScriptRunner Jobs is just a nice UI around Jira Services. In the past one would have created a com.onresolve.jira.groovy.GroovyService Jira Service directly)
  • Create a *Custom Scheduled Job:

    Image Added
    For User pick an account with the Jira Administrators global permission. You might like to create a dedicated role account ('deactivator') as I have in the screenshot, so that the Job isn't tied to a user account, but this does cost a license slot.
  • Click Run Now to run the script interactively.
    Image Added
    The Logs  tab will show what actions the script took (or would have taken if you commented out updateUser):
    Image Added
  • If all looks good, click Add to permanently add the Job.
  • Go to the Scriptrunner Script Console and do a test run:
    Image Removed
  • Warning

    I am finding that users are not actually deactivated, when the script is run like this as a service. The script runs successfully judging by the logs, but users are unaffected. YMMV - I have not yet debugged this, and it may affect only my Jira 8.5.1 instance.

    If all looks good, go to Jira's Services  admin page, and add a service of type com.onresolve.jira.groovy.GroovyService 
    Image Removed

ScriptRunner Solution with SQL Rules

...

Here is Postgres-flavoured SQL, creating a queries.inactive_users materialized view, of users that can be deactivated (source at https://github.com/redradishtech/jira-user-deactivator-groovy/blob/master/active_users.sql):

Include Code
languagesql
urlhttps://raw.githubusercontent.com/redradishtech/jira-user-deactivator-groovy/master/inactive_users.sql

Here is a corresponding Groovy script that reads usernames from the view, and deactivates those accounts (source):

Include Code
languagegroovy
urlhttps://raw.githubusercontent.com/redradishtech/jira-user-deactivator-groovy/master/deactivate-inactive-jira-users.groovy

...

The script should be installed in $JIRAHOME/scripts/jira-user-deactivator-groovy/deactivate_inactive_users.groovy and ande invoked automatically as a service, as described above.

...

As of , the only relevant plugin is Manage Inactive Users. This free plugin also supports deactivating users in external user bases like Okta and Google Apps.

...

Without any plugins, the cleanest solution would be a script utilitizing utilizing Jira's REST interface. The script would search for inactive users with Crowd CQL, then deactivate them. A REST solution would have the advantage of also working on Cloud Jira.

...

In a perfect world Jira would let us find exactly the users we want to deactivate with Crowd Query Language expression lastLogin > -6m OR (!lastLogin AND createdDate<-6m). Sadly 'lastLogin.lastLoginMillis' is considered a 'secondary' property which Crowd CQL doesn't support. Crowd CQL also doesn't support relative dates like '-6m'.

...

Another spanner in the works: Jira only gained a user deactivate REST method in  JIRA 8.3+. See 

Jira
serverCreate and track feature requests for Atlassian products.
serverId144880e9-a353-312f-9412-ed028e8166fa
keyJRASERVER-44801
.  Users of earlier releases would have to write their own REST endpoint using ScriptRunner: https://www.mos-eisley.dk/display/ATLASSIAN/Deactivate+a+User+via+REST

Given the potential slowness, and lack of REST support, I didn't pursue this route too far.

...

I haven't researched this much further, as instances I work with all have ScriptRunner available.

What about Confluence?

There is now a Confluence version of the inactive_users  SQL at https://github.com/redradishtech/jira-user-deactivator-groovy/blob/master/inactive_users_confluence.sql. Note that the SQL doesn't limit itself to Internal directories yet. I haven't made a Groovy deactivation script based around it yet.

Conclusion

Using ScriptRunner, we have implemented a means for Jira to automatically deactivate inactive users, thus saving license slots. This is (to my knowledge, as of  ) the only implementation that handles never-logged-in users. Users who require more flexibility can use the SQL-augmented approach.

...