Created
December 14, 2022 20:00
-
-
Save jay0lee/656d1a755b69984a2f849de59f252171 to your computer and use it in GitHub Desktop.
PoC script to create a new Workspace user using a GCP service account
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
### This script requires a service account private key JSON credentials file. | |
### The service account should be granted an admin role in your domain that | |
### authorizes it to create users. See: | |
### | |
### https://support.google.com/a/answer/9807615?hl=en&ref_topic=9832445&fl=1#zippy=%2Cassign-a-role-to-a-service-account | |
### | |
### This script requires PyJWT and requests. Install it by running: | |
### | |
### pip3 install PyJWT | |
### pip3 install requests | |
### | |
### Example usage on Linux with curl to call Admin SDK Directory API users.create() | |
### | |
### python3 ~/create-user.py \ | |
### --file ./service-account-private-key.json \ | |
### --user-email newuser@example.com \ | |
### --firstname New \ | |
### --lastname User \ | |
### --password p@ssw3rd | |
### | |
import argparse | |
import http.client | |
import json | |
import os | |
import sys | |
import time | |
import jwt | |
import requests | |
parser = argparse.ArgumentParser(description='Create a Google user using service account JWT auth') | |
parser.add_argument('--file', | |
help='Service account private key credential file.', | |
required=True, | |
dest='cred_file') | |
parser.add_argument('--user-email', | |
required=True, | |
help='Email address for new Google Workspace / Cloud Identity user.', | |
dest='useremail') | |
parser.add_argument('--firstname', | |
required=True, | |
help='First name / given name for new user.', | |
dest='firstname') | |
parser.add_argument('--lastname', | |
required=True, | |
help='Last name / family name for new user.', | |
dest='lastname') | |
parser.add_argument('--password', | |
required=True, | |
help='Password for new user. Must be at least 8 characters and meet admin console password requirements.', | |
dest='password') | |
parser.add_argument('--debug', | |
action='store_true', | |
help='Enable verbose debugging of JWT token and HTTP request.', | |
dest='debug') | |
args = parser.parse_args() | |
# read the service account private key file downloaded from GCP console service account keys. | |
# https://cloud.google.com/iam/docs/creating-managing-service-account-keys | |
if not os.path.isfile(args.cred_file): | |
print(f'ERROR: {args.cred_file} does not exist') | |
sys.exit(1) | |
with open(args.cred_file, 'r') as f: | |
try: | |
sa_info = json.load(f) | |
except json.JSONDecodeError: | |
print(f'ERROR: {args.cred_file} is not valid JSON. This doesn\'t look like a service account private key file.') | |
sys.exit(1) | |
if not 'private_key' in sa_info: | |
print(f'ERROR: no private_key in {args.cred_file}. This doesn\'t look like a service account private key file.') | |
sys.exit(1) | |
# Enable HTTP debugging if --debug is supplied | |
if args.debug: | |
http.client.HTTPConnection.debuglevel = 1 | |
# formulate the JWT we'll use as an auth header | |
# https://developers.google.com/identity/protocols/oauth2/service-account#jwt-auth | |
iat = int(time.time()) | |
exp = iat + 3600 | |
payload = {'iss': sa_info['client_email'], | |
'aud': 'https://admin.googleapis.com/', | |
'iat': iat, | |
'exp': exp, | |
'sub': sa_info['client_email']} | |
headers = {'kid': sa_info['private_key_id']} | |
# sign our JWT with our service account private key | |
signed_jwt = jwt.encode(payload, | |
sa_info['private_key'], | |
headers=headers, | |
algorithm='RS256') | |
# call our API to create a user | |
url = 'https://admin.googleapis.com/admin/directory/v1/users' | |
headers = {'Authorization': f'Bearer {signed_jwt}'} | |
body = {'primaryEmail': args.useremail, | |
'password': args.password, | |
'name': { | |
'givenName': args.firstname, | |
'familyName': args.lastname, | |
}, | |
} | |
r = requests.post(url, | |
headers=headers, | |
json=body) | |
# Dump the JSON data for the new user | |
print(json.dumps(r.json(), | |
indent=4, | |
sort_keys=True)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment