in source/soca/cluster_web_ui/api/v1/ldap/activedirectory/user.py [0:0]
def post(self):
"""
Create a new LDAP user
---
tags:
- User Management
parameters:
- in: body
name: body
schema:
required:
- user
- password
- sudoers
- email
optional:
- uid
- gid
properties:
user:
type: string
description: user you want to create
password:
type: string
description: Password for the new user
sudoers:
type: boolean
description: True (give user SUDO permissions) or False
email:
type: string
description: Email address associated to the user
uid:
type: integer
description: Linux UID to be associated to the user
gid:
type: integer
description: Linux GID to be associated to user's group
responses:
200:
description: User created
203:
description: User already exist
400:
description: Malformed client input
"""
parser = reqparse.RequestParser()
parser.add_argument('user', type=str, location='form')
parser.add_argument('password', type=str, location='form')
parser.add_argument('sudoers', type=int, location='form')
parser.add_argument('email', type=str, location='form')
parser.add_argument('shell', type=str, location='form')
parser.add_argument('uid', type=int, location='form') # 0 = no value specified, use default one
parser.add_argument('gid', type=int, location='form') # 0 = no value specified, use default one
args = parser.parse_args()
user = ''.join(x for x in args["user"] if x.isalpha() or x.isdigit()).lower() # Sanitize input
password = args["password"]
sudoers = args["sudoers"]
email = args["email"]
uid = args["uid"]
gid = args["gid"]
shell = args["shell"]
group = f"{args['user']}{config.Config.GROUP_NAME_SUFFIX}"
logger.info(f"Received New User creation: user: {user}, sudoers {sudoers}, email {email}, uid {uid}, gid {gid}, shell {shell}")
if user is None or password is None or sudoers is None or email is None:
return errors.all_errors("CLIENT_MISSING_PARAMETER", "user (str), password (str), sudoers (bool) and email (str) parameters are required")
if shell is None:
shell = "/bin/bash"
if user.lower() in password.lower():
return errors.all_errors("DS_PASSWORD_USERNAME_IN_PW")
if user.lower() == "admin":
return errors.all_errors("DS_PASSWORD_USERNAME_IS_ADMIN")
get_id = get(config.Config.FLASK_ENDPOINT + '/api/ldap/ids',
headers={"X-SOCA-TOKEN": config.Config.API_ROOT_KEY},
verify=False) # nosec
if get_id.status_code == 200:
current_ldap_ids = (json.loads(get_id.text))
else:
logger.error("/api/ldap/ids returned error : " + str(get_id.__dict__))
return {"success": False, "message": "/api/ldap/ids returned error: " + str(get_id.__dict__)}, 500
# Note: parseaddr adheres to rfc5322 , which means user@domain is a correct address.
# You do not necessarily need to add a tld at the end
if "@" not in parseaddr(email)[1]:
return errors.all_errors("INVALID_EMAIL_ADDRESS")
if uid == 0:
uid = current_ldap_ids["message"]['proposed_uid']
else:
if uid in current_ldap_ids["message"]['uid_in_use']:
return errors.all_errors("UID_ALREADY_IN_USE")
if gid == 0:
gid = current_ldap_ids["message"]['proposed_gid']
else:
if gid in current_ldap_ids["message"]['gid_in_use']:
return errors.all_errors("GID_ALREADY_IN_USE")
try:
conn = ldap.initialize(f"ldap://{config.Config.DOMAIN_NAME}")
conn.simple_bind_s(f"{config.Config.ROOT_USER}@{config.Config.DOMAIN_NAME}", config.Config.ROOT_PW)
conn.protocol_version = 3
conn.set_option(ldap.OPT_REFERRALS, 0)
dn_user = f"cn={user},ou=Users,ou={config.Config.NETBIOS},{config.Config.LDAP_BASE}"
attrs = [
('objectClass', ['top'.encode('utf-8'),
'person'.encode('utf-8'),
'user'.encode('utf-8'),
'organizationalPerson'.encode('utf-8')]),
('displayName', [str(user).encode('utf-8')]),
('mail', [email.encode('utf-8')]),
('sAMAccountName', [str(user).encode('utf-8')]),
('userPrincipalName', [str(user + "@" + config.Config.DOMAIN_NAME).encode('utf-8')]),
('cn', [str(user).encode('utf-8')]),
('uidNumber', [str(uid).encode('utf-8')]),
('loginShell', [shell.encode('utf-8')]),
('homeDirectory', (str(user) + '/' + str(user)).encode('utf-8'))]
# Create group first to prevent GID issue
create_user_group = post(config.Config.FLASK_ENDPOINT + "/api/ldap/group",
headers={"X-SOCA-TOKEN": config.Config.API_ROOT_KEY},
data={"group": f"{group}", "gid": gid},
verify=False) # nosec
if create_user_group.status_code != 200:
return errors.all_errors("COULD_NOT_CREATE_GROUP", str(create_user_group.text))
# Create user
conn.add_s(dn_user, attrs)
# Wait for the account to be sync
time.sleep(30)
# Reset password via Lambda
change_password = post(config.Config.FLASK_ENDPOINT + '/api/user/reset_password',
headers={"X-SOCA-TOKEN": config.Config.API_ROOT_KEY},
data={"user": user,
"password": password},
verify=False) # nosec
logger.info(f"Checking password reset request: {change_password.text}")
if change_password.status_code != 200:
return errors.all_errors("DS_CREATED_USER_NO_PW", str(change_password.text))
logger.info("Sleeping 10 seconds to make sure domain controllers are in sync")
time.sleep(10)
# Add user to group, need to wait 30 for account sync on AD
'''
update_group = put(config.Config.FLASK_ENDPOINT + "/api/ldap/group",
headers={"X-SOCA-TOKEN": config.Config.API_ROOT_KEY},
data={"group": f"{user}group",
"user": user,
"action": "add"},
verify=False) # nosec
if update_group.status_code != 200:
return errors.all_errors("UNABLE_TO_ADD_USER_TO_GROUP", f"User/Group created but could not add user to his group due to {update_group.json()}")
'''
# Create home directory
logger.info("About to create home directory for user")
if create_home(user, group) is False:
return errors.all_errors("UNABLE_CREATE_HOME", "User added but unable to create home director")
logger.info(f"About to generate API KEY for {user}")
# Create API Key
try:
get(config.Config.FLASK_ENDPOINT + "/api/user/api_key",
headers={"X-SOCA-TOKEN": config.Config.API_ROOT_KEY},
params={"user": user},
verify=False).json() # nosec
except Exception as err:
logger.error("User created but unable to create API key. SOCA will try to generate it when user log in for the first time " + str(err))
# Add Sudo permission
if sudoers == 1:
logger.info(f"Adding SUDO permissions to user {user}")
grant_sudo = post(config.Config.FLASK_ENDPOINT + "/api/ldap/sudo",
headers={"X-SOCA-TOKEN": config.Config.API_ROOT_KEY},
data={"user": user},
verify=False # nosec
)
if grant_sudo.status_code != 200:
return errors.all_errors("UNABLE_TO_GRANT_SUDO", "User added but unable to give admin permissions")
logger.info("User added successfully")
return {"success": True, "message": "Added user"}, 200
except Exception as err:
return errors.all_errors(type(err).__name__, err)