Skip to content

Instantly share code, notes, and snippets.

@iameskild
Last active November 6, 2023 15:58
Show Gist options
  • Save iameskild/07b7578b16ba9d389659e086cc021274 to your computer and use it in GitHub Desktop.
Save iameskild/07b7578b16ba9d389659e086cc021274 to your computer and use it in GitHub Desktop.
import csv
import json
import uuid
import time
def update_json_from_csv(csv_file, json_file):
users = []
with open(csv_file, 'r') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
user = {
"id": str(uuid.uuid4()),
"createdTimestamp": int(time.time() * 1000),
"username": row["email"],
"enabled": True,
"totp": False,
"emailVerified": False,
"firstName": row["first_name"],
"lastName": row["last_name"],
"email": row["email"],
"disableableCredentialTypes": [],
"requiredActions": [
"UPDATE_PASSWORD"
],
"notBefore": 0,
"credentials": [
{
"type": "password",
"value": "123",
}
],
"access": {
"manageGroupMembership": True,
"view": True,
"mapRoles": True,
"impersonate": True,
"manage": True
},
"groups": [
"analyst"
]
}
users.append(user)
with open(json_file, 'w') as jsonfile:
json.dump({"users": users}, jsonfile, indent=4)
# Usage example
csv_file = "users.csv"
json_file = "output.json"
update_json_from_csv(csv_file, json_file)
@iameskild
Copy link
Author

if you have a users.csv in the following format:

first_name,last_name,email
alex,test,alex@test.com

It will generate:

{
    "users": [
        {
            "id": "0c1f6c49-270b-4b34-b39c-eb084e904797",
            "createdTimestamp": 1682374050971,
            "username": "alex@test.com",
            "enabled": true,
            "totp": false,
            "emailVerified": false,
            "firstName": "alex",
            "lastName": "test",
            "email": "alex@test.com",
            "disableableCredentialTypes": [],
            "requiredActions": [
                "UPDATE_PASSWORD"
            ],
            "notBefore": 0,
            "credentials": [
                {
                    "type": "password",
                    "value": "123"
                }
            ],
            "access": {
                "manageGroupMembership": true,
                "view": true,
                "mapRoles": true,
                "impersonate": true,
                "manage": true
            }
        }
    ]
}

Which can then be imported into keycloak to create those users. Each of these users will have the same password (123) but will be prompted to create a new password upon first login.

@rsignell-usgs
Copy link

I found I had to modify the read statement to successfully load the CSV file I was given, specifying encoding='utf-8-sig':

import csv
import json
import uuid
import time

def update_json_from_csv(csv_file, json_file):
    users = []

    with open(csv_file, 'r', encoding='utf-8-sig') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            user = {
                "id": str(uuid.uuid4()),
                "createdTimestamp": int(time.time() * 1000),
                "username": row["email"],
                "enabled": True,
                "totp": False,
                "emailVerified": False,
                "firstName": row["first_name"],
                "lastName": row["last_name"],
                "email": row["email"],
                "disableableCredentialTypes": [],
                "requiredActions": [
                    "UPDATE_PASSWORD"
                ],
                "notBefore": 0,
                "credentials": [
                    {
                        "type": "password",
                        "value": "123",
                    }
                ],
                "access": {
                    "manageGroupMembership": True,
                    "view": True,
                    "mapRoles": True,
                    "impersonate": True,
                    "manage": True
                },
                "groups": [
                    "users"
                ]
            }
            users.append(user)

    with open(json_file, 'w') as jsonfile:
        json.dump({"users": users}, jsonfile, indent=4)

# Usage example
csv_file = "clinic3.csv"
json_file = "clinic3.json"
update_json_from_csv(csv_file, json_file)

@kcpevey
Copy link

kcpevey commented Oct 30, 2023

I needed to create some generic users for a conference tutorial so I made some modifications of my own:

def create_keycloak_user_json(users=None, json_file='output.json', password='nebari_user123!@', groups=['users']):
    """
    users: list[dict]
        list of dictionaries with keys: first_name, last_name, email
    json_file: str
        filepath for output json file
    password: str
        default password for all users
    groups: list[str]
        groups in which to place all users
    """
        
    json_users = []
    for entry in users:
        user = {
            "id": str(uuid.uuid4()),
            "createdTimestamp": int(time.time() * 1000),
            "username": entry["email"],
            "enabled": True,
            "totp": False,
            "emailVerified": False,
            "firstName": entry["first_name"],
            "lastName": entry["last_name"],
            "email": entry["email"],
            "disableableCredentialTypes": [],
            "requiredActions": [
                "UPDATE_PASSWORD"
            ],
            "notBefore": 0,
            "credentials": [
                {
                    "type": "password",
                    "value": password,
                }
            ],
            "access": {
                "manageGroupMembership": True,
                "view": True,
                "mapRoles": True,
                "impersonate": True,
                "manage": True
            },
            "groups": groups
        }
        json_users.append(user)
    
    
    with open(json_file, 'w') as jsonfile:
        json.dump({"users": json_users}, jsonfile, indent=4)
    
def create_generic_users(prefix, number_of_entries):
    """Create a list of user dictionaries with generic usernames"""
    entries = []
    for idx in range(number_of_entries):
        user_dict = {}
        name = f'{prefix}_{idx}'
        user_dict['first_name'] = name
        user_dict['last_name'] = ''
        user_dict['email'] = name
        entries.append(user_dict)
        
    return entries
       

You'd call these like this:

user_list = create_generic_users('generic_user', 100)
create_keycloak_user_json(users=user_list, password='nebari_user!@', json_file='output.json', groups=['users', 'analyst', 'developer'])

This will create a json file prepared for uploading to keycloak with 100 users with names like generic_user_1, generic_user_2, etc.

@rsignell
Copy link

rsignell commented Nov 6, 2023

How would you modify this if you use github authentication in keycloak and all you have is a list of github usernames?

@iameskild
Copy link
Author

@rsignell the important thing for github auth to keep in mind is that the user's github username will also be their username in keycloak. That means you can modify line 15 so that it pull row['github_username'] (if that column exists in your csv).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment