Skip to content

Instantly share code, notes, and snippets.

@icelander
Last active July 23, 2020 15:34
Show Gist options
  • Save icelander/2b7e36e7fbfe3d9efa91c08c9a8a2a9e to your computer and use it in GitHub Desktop.
Save icelander/2b7e36e7fbfe3d9efa91c08c9a8a2a9e to your computer and use it in GitHub Desktop.
Generate Okta Import CSV from Mattermost Users
#!/bin/ruby
require 'csv'
require 'yaml'
require 'httparty'
require 'uri'
### users_to_csv.rb
#
## About
#
# users_to_csv.rb is a script that automates the process of migrating
# Mattermost users to Okta by generating a CSV file that can be imported into
# Okta as well as modifying the Mattermost user to use SAML as the login
# service. This is very useful when setting up a test or demo environment to
# showcase Okta SAML & LDAP.
#
## Usage:
#
# 1. Create a file named `conf.yaml` with this format:
#
# test_server:
# url: https://<Mattermost Server URL>/ <- INCLUDE TRAILING SLASH
# login_id: <Mattermost admin username>
# auth_token: <Auth Token>
#
# OR
#
# test_server:
# url: https://<Mattermost Server URL>/ <- INCLUDE TRAILING SLASH
# login_id: <Mattermost admin username>
# password: <Password>
#
# 2. Run it through Ruby: `ruby users_to_csv.rb`
#
## TODO List
#
# 1. Improve HTTParty Security
# 2. Handle pagination of users request
# 3. Skip Bot/Plugin users
# 4. Provision users in Okta instead of generating a CSV
$config = YAML.load(
File.open('conf.yaml').read
)
class MattermostApi
include HTTParty
format :json
# UNCOMMENT NEXT LINE TO DEBUG REQUESTS
# debug_output $stdout
def initialize(config)
# Default Options
@options = {
headers: {
'Content-Type' => 'application/json',
'User-Agent' => 'Mattermost-HTTParty'
},
# TODO Make this more secure
verify: false
}
# check the config for mattermost_url
if ! (config.key?("url") && url_valid?(config['url']))
raise 'url is required in configuration'
end
@base_uri = config['url'] + 'api/v4/'
token = nil
if config.key?('auth_token')
token = config['auth_token']
else
# Use password login
if (config.key?('login_id') && config.key?('password'))
token = get_login_token(config['login_id'], config['password'])
end
end
if token.nil?
raise 'token not set, check for token or login_id and password'
end
@options[:headers]['Authorization'] = "Bearer #{token}"
@options[:body] = nil
end
def url_valid?(url)
url = URI.parse(url) rescue false
end
def make_saml_user(user)
url = "users/#{user['id']}/auth"
options = @options
options[:body] = {'auth_data' => user['email'], 'auth_service' => 'saml', 'password' => 'U$er12345'}.to_json
JSON.parse(self.class.put("#{@base_uri}#{url}", options).to_s)
end
def get_all_users
get_url('users')
end
def get_url(url)
# TODO: Make this handle pagination
JSON.parse(self.class.get("#{@base_uri}#{url}", @options).to_s)
end
end
$mm = MattermostApi.new($config['test_server'])
users = $mm.get_all_users
# Maps Okta CSV fields to Mattermost user properties
csv_fields = {'login' => 'email',
'firstName' => 'first_name',
'lastName' => 'last_name',
'middleName' => nil,
'honorificPrefix' => nil,
'honorificSuffix' => nil,
'email' => 'email',
'title' => 'position',
'displayName' => 'username',
'nickName' => 'nickname',
'profileUrl' => nil,
'secondEmail' => nil,
'mobilePhone' => nil,
'primaryPhone' => nil,
'streetAddress' => nil,
'city' => nil,
'state' => nil,
'zipCode' => nil,
'countryCode' => nil,
'postalAddress' => nil,
'preferredLanguage' => nil,
'locale' => 'locale',
'timezone' => nil,
'userType' => 'roles',
'employeeNumber' => nil,
'costCenter' => nil,
'organization' => nil,
'division' => nil,
'department' => nil,
'managerId' => nil,
'manager' => nil}
# TODO: Provision user via Okta API
CSV.open("./okta_import.csv", "wb") do |csv|
csv << csv_fields.keys
users.each do |user|
# TODO: Skip Bot/Plugin users, e.g. Gitlab Plugin
next if user['auth_service'] == 'saml'
user_data = []
puts "Processing user #{user['id']} - #{user['email']}"
$mm.make_saml_user
csv_fields.each do |okta_index, mattermost_index|
# TODO: Filter by auth_method
# TODO: Fix Formatting of locale Valid values are concatenation of the ISO 639-1 two letter language code
if mattermost_index.nil?
user_data << ""
else
puts "\tSetting #{okta_index} to #{user[mattermost_index]}"
user_data << user[mattermost_index]
end
end
csv << user_data
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment