[Solved] Help! LDAP Migration w/ New Usernames

We are moving to a new domain for authentication and I am not sure about how to go about migrating.

  • Email addresses are staying the name
  • All usernames are changing to a new format
  • LDAP is changing

We are currently running version 9.0.5 of Gitlab CE, though we will update to latest before migrating. My current guess on how the process should go without messing up a bunch of history, permissions, etc. is:

  1. Change usernames from current format to new format (we have a list of before/after)
  2. Change system config to new LDAP settings
  3. Is there some individual user settings that need to be changed too for LDAP?
  4. Restart?
  5. Hope and Pray?

Edit: Solution
I ended up writing ruby functions that I could call on the ‘gitlab-rails console production’

  1. First, I had to update the email addresses to the ones that are in the new LDAP system (they set up a proxy to our old email addresses, but mail attribute is set to new one)
  2. To get around the reconfirmation issue for email change, I called ‘user.skip_reconfirmation!’ before I called ‘user.save!’
  3. Next I changed the system config with the new LDAP settings
  4. Reconfigured and restarted Gitlab
  5. Then I ran my second ruby function from the console to update all of the usernames to the new format

After this, everyone was able to login with their new usernames and their internal identities updated properly.

@alison-gravley Please show your script for me, i want change ldap too.

  1. Login to your gitlab server (the linux box, not the web interface)
  2. I created a script and put my .rb file in /opt/gitlab/embedded/service/gitlab-rails/lib/
  3. I used a tab delimited list of users with their names, gitlab id numbers, old/new email, old/new username, etc.
  4. It is important that any input files are somewhere that gitlab won’t complain about permissions. I ended up putting mine in /tmp
  5. Open up the gitlab rails console by typing in gitlab-rails console production
  6. From here you can test your commands directly before actually calling functions from your script.
  7. To call a function in your rb

Some command examples on how to search for and update users:

  1. Find the user by whatever method is easiest. Here are a few options
    a. user = User.find_by(email: 'email@email.com')
    b. user = User.find_by(username: 'myusername')
    c. user = User.where(id: 2).first
  2. To update a username:
    a. user.username = 'newuser'
    b. user.save!
  3. To update an email:
    a. user.email = 'newemail'
    b. user.skip_reconfirmation!
    c. user.save!
  4. To forcibly unblock a user:
    a. user.state = 'active'
    b. user.save!

The steps I took in my migration:

  1. Update email addresses
    a. update_emails('/tmp/all_gitlab_users.txt')
  2. Change gitlab.rb to new ldap configuration
  3. gitlab-ctl reconfigure
  4. gitlab-ctl restart
  5. Double check ldap config with gitlab-rake gitlab:ldap:check
  6. If you used a different provider name in your new ldap config, run the rename provider command
    a. gitlab-rake gitlab:ldap:rename_provider[ldapmain,ldapnewmain]
  7. gitlab-ctl restart
  8. Update usernames
    a. update_usernames('/tmp/all_gitlab_users.txt')
  9. Have users login with new credential through the web interface. Should be ok now. If they have a “1” in their username that means email addresses didn’t match in the new ldap server.

Here is the contents of my migration.rb file:

#!/usr/bin/env ruby

def update_emails(input_file)
  file=input_file

  f = File.open(file, "r")
  puts "Opening file #{file} for email conversion..."

  #<user_id> <current_username> <new_username> <new_email> <current_email> <real_name>
  f.each_line { |line|
    #Split the string by tabs
    tokens = line.split("\t")
    if tokens.size == 6
      user_id = tokens[0]
      curr_user = tokens[1]
      upd_user = tokens[2]
      upd_email = tokens[3]
      curr_email = tokens[4]
      real_name = tokens[5]

      user = User.where(id: user_id).first
      if user
        puts "Updating Email For - ID: #{user_id}, CurrentUsername: #{curr_user}, Current Email: #{user.email}, New Email #{upd_email}"
        user.email = upd_email
        user.skip_reconfirmation!
        user.save!
      else
       puts "Unable to find user with id = #{user_id}. CurrentUsername: #{curr_user}, Real Name: #{real_name}"
      end
    else
      puts "Error! Line does not have 6 tokens. Has #{tokens.size}: #{line}"
    end
  }
  f.close
  puts "Finished Processing Email Updates"
end

def update_usernames(input_file)
  file=input_file

  f = File.open(file, "r")
  puts "Opening file #{file} for username conversion..."

  #<user_id> <current_username> <new_username> <new_email> <current_email> <real_name>
  f.each_line { |line|
    #Split the string by tabs
    tokens = line.split("\t")
    if tokens.size == 6
      user_id = tokens[0]
      curr_user = tokens[1]
      upd_user = tokens[2]
      upd_email = tokens[3]
      curr_email = tokens[4]
      real_name = tokens[5]

      user = User.where(id: user_id).first
      if user
        puts "Updating Username For - ID: #{user_id}, CurrentUsername: #{curr_user}, Current Username: #{user.username}, New Username #{upd_user}"
        user.username = upd_user
        user.save!
      else
       puts "Unable to find user with id = #{user_id}. CurrentUsername: #{curr_user}, Real Name: #{real_name}"
      end
    else
      puts "Error! Line does not have 6 tokens. Has #{tokens.size}: #{line}"
    end
  }
  f.close
  puts "Finished Processing Username Updates"
end
2 Likes

Thank you very much.

Hi,

thank you so much fo this post.

Can you attach all_gitlab_users.txt example?

Thank you

marco

Works for me. Great. Thankx!

I’ve found less complicated way, for me, via gitlab api.
I need move users from openldap to ActiveDirectory with change username, email and extern_uid.

Created file with users list
/tmp/user_file

content

gitlab_user1_id gitlab_user1_username ad_user1_dn_base64 ad_user1_username ad_user1_mail
gitlab_user2_id gitlab_user2_username ad_user1_dn_base64 ad_user2_username ad_user2_mail

and do it with bash via gitlab api

#!/bin/bash

export GITLAB_TOKEN=glpat-XXXXXXX
export CI_API_V4_URL="https://gitlab.example.com/api/v4"
export GITLAB_PROVIDER=ldapmain

cat /tmp/user_file | while read gitlab_user_id gitlab_user_username ad_user_dn_base64 ad_user_username ad_user_mail
do
  ad_user_dn_urlencode=`echo -ne "$ad_user_dn_base64" | base64 -d | jq -Rr @uri`
  curl -X PUT -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${CI_API_V4_URL}/users/$gitlab_user_id?username=$ad_user_username&email=$ad_user_mail&extern_uid=$ad_user_dn_urlencode&provider=${GITLAB_PROVIDER}&skip_reconfirmation=true"
done

PS:

  • ad_user1_dn_base64 in base64 because ldapsearch returns DN in base64.
  • I didn’t add any checks in the bash script because there were about 50 users.
  • important note: user have to not have container registry in his personal repositories. Check it before.