I recently had to deal with an Bitbucket user issue where people were being added to a JIRA group automatically that granted r/w access to Bitbucket. Nearly half of the people who were in this group had never even logged into Bitbucket, but they counted against our license seats. We were running dangerously close to running out of seats and had only hours to spare. Rather than focus on the problems that lead up to this situation, I’d rather focus on the core question “Who’s actually using Bitbucket?” and how we regained nearly 1000 seats.
Problem #1: How many people are actually using Bitbucket?
In order to cast a wide enough net to find everyone, our metric was “Who’s ever logged into Bitbucket?” To do that, we queried the database (MySQL) and exported the results to CSV. Below is the query and what the resulting output looked like.
select cua.attribute_value, cu.user_name from cwd_user_attribute as cua inner join cwd_user as cu on cu.id = cua.user_id where cua.attribute_name = "lastAuthenticationTimestamp";
The resulting CSV looked something like this:
attribute_value,user_name 1497642118994,user_a 1497642069440,user_b 1497642117652,user_c
Problem #2: How do we put these people in a new permissions group?
To solve that, we turned to JIRAs REST APIs. First we created a new group in JIRA, then we wrote a little bit of code to loop through the CSV and add those folks to the group. I need to preface that this snippet was written very hurriedly to solve the problem (I have anĀ ego to protect). This is written in Python 3 and uses the Requests module.
import requests import csv url = "https://<JIRA-URL>/rest/api/2/group/user?groupname=group-name" admin_user = "admin" admin_pass = "password" headers = {'content-type': 'application/json'} post_data = """{"name": "%s"}""" def make_json(user): return(post_data % user) with open('active_users.csv', newline='') as csv_file: reader = csv.reader(csv_file) for row in reader: user = row[1] response = requests.post(url, auth=(admin_user, admin_pass), headers=headers, data=make_json(user)) if response.status_code == 200 or response.status_code == 201: print('{} added to new group'.format(user)) else: print('Failed to add {} to new group'.format(user)) print('Status code: {}'.format(response.status_code)) print('API Response:\n\n' + response.text)
There were a few errors, but they seemed to all just be local Bitbucket users. No big deal.
Problem #3: How do we update all of our Bitbucket projects with this new group?
Unfortunately, Atlassian does not provide a way to bulk edit project or repository configurations. This is terrible oversight in my opinion, but is out of scope for this post. Still, though…
To solve this problem, we turned to Script Runner for Bitbucket. We performed the work in this order to prevent anyone from running into errors.
- Add the new group to all of the projects.
- Add the new group to global permissions.
- Remove the old group from global permissions.
- Remove the old group from all of the projects.
We used the provided code snippets from Adaptavist. See docs here.