Note:
- Este tutorial requiere acceso a Oracle Cloud. Para registrarse en una cuenta gratuita, consulte Introducción a la cuenta gratuita de Oracle Cloud Infrastructure.
- Utiliza valores de ejemplo para credenciales, arrendamiento y compartimentos de Oracle Cloud Infrastructure. Al finalizar el laboratorio, sustituya estos valores por otros específicos del entorno en la nube.
Supresión de usuarios inactivos de dominios de identidad de OCI IAM según UserStatus y LastSuccessfulLoginDate mediante Python
Introducción
Oracle Cloud Infrastructure (OCI) es una plataforma en la nube capaz de proporcionar una gama de servicios en la nube que incluyen almacenamiento, redes e infraestructura. Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) es un servicio que permite gestionar el acceso a los recursos de OCI. Proporciona autenticación y autorización para usuarios y grupos.
La supresión de usuarios inactivos en función de su última fecha de conexión correcta en los dominios de identidad de OCI IAM puede resultar especialmente útil en el contexto del modelo de precios por usuario de OCI por varios motivos:
-
Optimización de costos: OCI sigue un modelo de precios por usuario, lo que significa que se le factura por cada cuenta de usuario. Al identificar y eliminar usuarios inactivos regularmente, puede reducir significativamente sus costos de suscripción. Esta optimización de costos se vuelve aún más crítica a medida que su organización se amplía y crece el número de usuarios.
-
Mejora de seguridad: las cuentas de usuario inactivas son un posible riesgo de seguridad. Estas cuentas ya no pueden ser utilizadas por usuarios legítimos, pero aún pueden ser explotadas por actores maliciosos si se dejan sin supervisión. La supresión de usuarios inactivos garantiza que solo las personas autorizadas tengan acceso a sus recursos de OCI, lo que reduce la superficie de ataque y mejora la seguridad general.
-
Resource Management: la gestión de un gran número de cuentas de usuario inactivas puede ser una carga administrativa. Desordena su entorno de IAM y dificulta el enfoque en las cuentas de usuario activas. Automatizar el proceso de identificación y supresión de usuarios inactivos libera recursos administrativos y permite a su equipo concentrarse en tareas más estratégicas.
-
Cumplimiento: los estándares de cumplimiento a menudo requieren que las organizaciones revisen y gestionen cuentas de usuario con regularidad. La supresión de usuarios inactivos puede ayudarle a cumplir los requisitos de conformidad y demostrar un compromiso con la seguridad y gobernanza de los datos.
Para implementar este proceso de manera efectiva, debajo del fragmento de python se puede usar para automatizar la identificación y supresión de usuarios inactivos en función de su última fecha de inicio de sesión correcta y su estado activo/inactivo. Al ejecutar estos scripts con regularidad, puedes mantener un entorno de IAM seguro y eficiente a la vez que optimizas tus costos en OCI.
Público Objetivo
Profesionales y administradores de IAM.
Objetivo
Suprima usuarios según el estado del usuario y lastSuccessfulLoginDate de los dominios de identidad de OCI IAM mediante la API de REST con Python.
Requisitos
-
Una suscripción activa a OCI.
-
Familiarícese con OCI IAM y Python.
-
Se necesita información sobre el uso de la API de REST de dominios de identidad de OCI IAM.
-
Usuario de IAM con autorización para gestionar aplicaciones (administrador de dominio de identidad, administrador de seguridad o administrador de aplicaciones).
-
Python 3.x instalado en el sistema.
-
Paquetes Python
urllib3
,requests
ydatetime
instalados.
Tarea 1: Creación de una aplicación confidencial en dominios de identidad de OCI IAM
Siga Oracle Identity Cloud Service: primera llamada de API de REST para crear una aplicación confidencial y recuperar el ID de cliente y el secreto de cliente, que se pueden utilizar para realizar una llamada de API de REST a OCI IAM para recuperar el token de acceso y los puntos finales de API posteriores.
Tarea 2: Configurar el archivo config.json
Configure el archivo de configuración en la máquina local. El archivo config.json
tiene información sobre la URL del dominio de identidad, el ID de cliente y el secreto de cliente que se utiliza para generar el token de acceso.
{
"iamurl" : "https://idcs-###########.identity.oraclecloud.com",
"client_id" : "#######################",
"client_secret" : "#######################"
}
Tarea 3: Obtener el token de acceso
Una vez que el archivo config.json
esté en su lugar, lo primero que debe hacer es generar el token de acceso, que se puede utilizar para realizar más llamadas de API de REST a los puntos finales de OCI IAM.
En el siguiente fragmento de código, la función get_encoded toma el ID de cliente y el secreto de cliente como argumentos y devuelve la cadena base64-encoded
. Esta cadena codificada se transfiere como argumento a la función get_access_token
como cabecera de autorización para obtener el token de acceso mediante una solicitud POST.
#get base64 encoded
def get_encoded(self,clid, clsecret):
encoded = clid + ":" + clsecret
baseencoded = base64.urlsafe_b64encode(encoded.encode('UTF-8')).decode('ascii')
return baseencoded
#get access token
def get_access_token(self,url, header):
para = "grant_type=client_credentials&scope=urn:opc:idm:__myscopes__"
response = requests.post(url, headers=header, data=para, verify=False)
jsonresp = json.loads(response.content)
access_token = jsonresp.get('access_token')
return access_token
#print access token
def printaccesstoken(self):
obj = IAM()
encodedtoken = obj.get_encoded(clientID, clientSecret)
extra = "/oauth2/v1/token"
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Authorization': 'Basic %s' % encodedtoken, 'Accept': '*/*'}
accesstoken = obj.get_access_token(idcsURL + extra, headers)
return accesstoken
Tarea 4: Manejar un lote de información de usuario (lastSuccessfulLoginDate, userStatus) para limpiar usuarios
Tenemos el token de acceso, mediante el cual podemos realizar más llamadas de API de REST a diferentes puntos finales de REST de dominios de identidad de OCI IAM. El fragmento de código siguiente muestra cómo estamos realizando una solicitud GET con las cabeceras y los parámetros necesarios en el punto final /admin/v1/Users
, para recuperar el número total de usuarios y, a continuación, calcular el número de iteraciones necesarias, según el número total de resultados y el recuento por solicitud.
-
La función obtiene la fecha actual en el formato AAAA-MM-DD y almacena en una variable
current_date
y, a continuación, itera los datos de cada usuario. -
En cada iteración, envía una solicitud GET con los parámetros adecuados para recuperar un lote de información de usuario (nombre de usuario, lastSuccessfulLoginDate y activo) y, a continuación, realiza algunas comprobaciones condicionales.
-
A continuación, el código, basado en comprobaciones condicionales definidas, agrega el nombre de usuario y el ID de usuario para todos los usuarios coincidentes en los archivos
username.txt
yuserid.txt
, respectivamente, y lo marca para su supresión. En primer lugar, comprueba el estado del usuario y, si es Falso (lo que significa inactivo), agrega el usuario a los archivostxt
y continúa con la siguiente iteración del bucle. A continuación, comprueba el estado del usuario y, si es Ninguno, imprime que _{user} nunca ha accedido. Tome la decisión de suprimirlo manualmente en la consola y continuar con la siguiente iteración del bucle. -
El script recupera la última fecha de conexión correcta del usuario, calcula el número de días desde la última conexión y lo imprime en la consola. Para cualquier usuario que no haya iniciado sesión durante más de 90 días, la secuencia de comandos procede a comprobar si el usuario tiene roles de administrador específicos asociados. Cualquier usuario que no haya iniciado sesión durante 90 días y tenga NO tenga roles de administrador se identifica y marca para su supresión.
-
Después de procesar todos los usuarios, se escribe un juego de ID de usuario que se va a suprimir en un archivo JSON
username.json
. Una solicitud de supresión masiva se prepara formateando los datos en un formato JSON específico. La solicitud de supresión en bloque se envía al punto final/admin/v1/Bulk
y se imprime un mensaje para indicar que se han suprimido los usuarios identificados. -
Después de todas las iteraciones, la función vuelve a la función principal.
Nota: Hay una sección de código comentada con explicaciones para acciones futuras o decisiones manuales, como el manejo de usuarios que nunca han accedido al sistema. Puede haber un escenario en el que un administrador no haya accedido a OCI IAM y puede que no desee suprimirlos.
def get_successfullogindate(self): extra = "/admin/v1/Users" obj = IAM() accesstoken = obj.printaccesstoken() headers = {'Authorization': 'Bearer ' + accesstoken} resp = requests.get(idcsURL+extra, headers=headers, verify=False) jsonresp = json.loads(resp.content) totalCount = jsonresp.get("totalResults") print("Total number of users: " + str(totalCount)) current_date = datetime.now().date() startIndex = 1 count = 50 loop = int(totalCount / count) extra2 = "/admin/v1/AppRoles" for i in range(loop + 1): param = { 'attributes': "username,active,urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User:lastSuccessfulLoginDate", 'startIndex': startIndex, 'count': count} resp = requests.get(idcsURL+extra, headers=headers, verify=False, params=param) startIndex += count jsonresp = json.loads(resp.content) tempjsn = jsonresp.get("Resources") for x in tempjsn: trimjsn = {} username = trimjsn['userName'] = x.get("userName") userid = x.get("id") userStatus = x.get("active") userState = x.get("urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User") if userStatus is False: print(username + " is in inactive state. Will be deleted.") with open('username.txt', 'a') as c: c.write(username) c.write('\n') with open('userID.txt', 'a') as d: d.write(userid) d.write('\n') continue if userState is None: print(username + " has never accessed. Kindly make a decision to delete it manually on console") # with open('username.txt', 'a') as c: # c.write(username) # c.write('\n') # with open('userID.txt', 'a') as d: # d.write(userid) # d.write('\n') # ** Uncomment the lines commented above to delete the users who have never accessed ** continue lastLoginDate = x['urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User']['lastSuccessfulLoginDate'] target_dates = datetime.strptime(lastLoginDate, '%Y-%m-%dT%H:%M:%S.%fZ').date() num_days = (current_date - target_dates).days #print(username + " Last logged in " + str(num_days) + " days ago") if num_days > 30: #print("entered if condition for more than 90 days ") params2 = {"filter": f'members[value eq "{userid}"] and app.value eq "IDCSAppId" and (displayName eq "Identity Domain Administrator" or displayName eq "Security Administrator" or displayName eq "Application Administrator" or displayName eq "User Administrator" or displayName eq "User Manager" or displayName eq "Help Desk Administrator" or displayName eq "Audit Administrator")'} resp2 = requests.get(idcsURL+extra2, headers=headers, verify=False, params=params2) jsonresp3 = json.loads(resp2.content) totalCount1 = jsonresp3.get("totalResults") if totalCount1 < 1: print(username + " has not Logged in for 90 days and has NO admin role. Will be deleted.") with open('username.txt', 'a') as c: c.write(username) c.write('\n') with open('userID.txt', 'a') as d: d.write(userid) d.write('\n') try: with open('userID.txt','r') as g: lines = len(g.readlines()) except FileNotFoundError: print("No users found to be Deleted by the Script") exit() x=0 while x<lines: with open('userID.txt','r') as e: content = e.readlines() id=content[x] id=id.rstrip(id[-1]) paradelete=json.dumps( { "method": "DELETE", "path": "/Users/"+id+"?forceDelete=true" } ) with open('username.json', 'a') as j: j.writelines(paradelete) j.write(',') x=x+1 with open('username.json', 'r') as file: data = file.read() with open('formatedData.json', 'a') as file1: file1.writelines('{ \n') file1.writelines('"schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],\n') file1.writelines('"Operations": [\n') data2=data.rstrip(data[-1]) file1.write(data2) file1.write(']}') headers = {'Authorization': 'Bearer ' + accesstoken} bulkdata = json.load(open('formatedData.json')) param = {'forceDelete': True} payload = json.dumps(bulkdata) headers2 = {'Content-Type': 'application/json','Authorization': 'Bearer ' + accesstoken, 'Accept': '*/*'} extra2="/admin/v1/Bulk" #respdelete = requests.request("POST",idcsURL + extra2, headers=headers2, verify=False, params=param,data=payload) print("The identified users has been deleted ") try: os.remove('userID.txt') os.remove('username.txt') os.remove('formatedData.json') os.remove('username.json') except FileNotFoundError: exit()
Tarea 5: Uso del script en OCI Cloud Shell
Una vez que el script está listo, se puede ejecutar fácilmente en la máquina local (con Python instalado) o en cualquier IDE que soporte el desarrollo de Python. Estamos utilizando OCI Cloud Shell para ejecutar el script y obtener el informe deseado.
-
Conéctese a la consola de OCI, abra Cloud Shell desde la esquina superior derecha de la pantalla y, a continuación, cargue el script de Python y el archivo
config.json
. -
Ejecute
python DeleteUser_PriorCheck_InactivePeriod60days_IsAdmin.py
.Nota:
DeleteUser_PriorCheck_InactivePeriod60days_IsAdmin.py
es el script de Python desarrollado mediante fragmentos de código anteriores.
Enlaces relacionados
Agradecimientos
-
Autor: Gautam Mishra (ingeniero sénior en la nube)
-
Contribuyente: Chetan Soni (ingeniero de soluciones en la nube)
Más recursos de aprendizaje
Explore otros laboratorios en docs.oracle.com/learn o acceda a más contenido de aprendizaje gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en Oracle Learning Explorer.
Para obtener documentación sobre el producto, visite Oracle Help Center.
Delete Inactive Users from OCI IAM Identity Domains Based on UserStatus and LastSuccessfulLoginDate Using Python
F89514-01
November 2023
Copyright © 2023, Oracle and/or its affiliates.