Note:

Activación de la rotación automática de credenciales de Oracle Cloud Infrastructure Identity and Access Management

Introducción

Este tutorial ayuda a rotar automáticamente las credenciales de Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) que son clave de API, token de autenticación, claves secretas de cliente y contraseñas de conexión de la consola de OCI. Se basa en la solución de problemas de Oracle Cloud Guard y en el servicio OCI Notifications. También cumple el intervalo de reglas de responsable de respuesta por defecto para rotar las credenciales de OCI IAM.

Oracle Cloud Guard detecta problemas basados en reglas definidas en las políticas. Una vez que se cumple una regla, se crea un problema.

Es una práctica recomendada de seguridad y recomendada por The Center for Internet Security Oracle Cloud Infrastructure Foundations (CIS OCI Foundations) Benchmark para rotar las credenciales cada 90 días.

Nota: Esta solución se ha probado para un dominio de identidad por defecto.

Objetivos

Requisitos

El administrador de OCI IAM debe crear:

Tarea 1: Creación y despliegue de OCI Functions

  1. Conéctese a la consola de OCI y haga clic en Cloud Shell en la navegación superior.

    Nota: También puede utilizar su propia herramienta de IDE para crear y desplegar una función.

  2. Cree una función mediante la CLI del proyecto de Fn desde Cloud Shell. Para obtener más información, consulte Creación, despliegue y llamada de una función Hola mundo.

    fn init --runtime python <function-name>
    
    Example: fn init --runtime python rotatecred-func
    
  3. Cambie el directorio al directorio creado recientemente.

  4. Cree una aplicación para desplegar la función con el siguiente comando.

    # Specify the OCID of subnet
    fn create app <app-name> --annotation oracle.com/oci/subnetIds='["<subnet OCID>"]'
    
    Example:  fn create app rotatecredapp --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.ap-mumbai-1.aaaaaaaabitp32dkyox37qa3tk3evl2nxivwb....."]'
    
  5. Copie y pegue el siguiente script en func.py sobrescribiendo el contenido existente.

    # python script for auto rotation of OCI IAM credentials
    import io
    import json
    import logging
    import oci
    import base64
    from fdk import response
    from Cryptodome.PublicKey import RSA
    
    # Get Resource Principal Credentials
    signer = oci.auth.signers.get_resource_principals_signer()
    
    # Initialize client
    identity_client = oci.identity.IdentityClient(config={}, signer=signer)
    onsclient = oci.ons.NotificationDataPlaneClient(config={}, signer=signer)
    vault_client = oci.vault.VaultsClient(config={}, signer=signer)
    
    # Get tenancy id and name
    tenancy_data = identity_client.get_tenancy(tenancy_id=signer.tenancy_id).data
    t_name = str(tenancy_data.name)
    t_id = signer.tenancy_id
    
    # Get secret OCID from comments
    def get_secret_ocids(comments_items,find_name):
       secret_ocid = ""
       for comment in comments_items:
          if comment.split(":")[0] == find_name:
                secret_ocid = comment.split(":")[1]
       return secret_ocid
    
    # Function to store secret in OCI vault
    def update_secret(vault_client,secret_id,new_value):
       # Base64 encode
       new_token_ascii = new_value.encode("ascii")
       base64_bytes = base64.b64encode(new_token_ascii)
       base64_string = base64_bytes.decode("ascii")
    
       # Create new version of secret
       vault_client.update_secret(secret_id=secret_id,update_secret_details=oci.vault.models.UpdateSecretDetails(secret_content=oci.vault.models.Base64SecretContentDetails(content_type="BASE64", content=base64_string)))
    
    def handler(ctx, data: io.BytesIO=None):
       try:
          cfg = ctx.Config()
          ons_topic = cfg["ons_topic"]
          body = json.loads(data.getvalue())
    
          # Get common parameters values
          e_time = str(body["eventTime"]).lstrip()
          problem_name = str(body["data"]["additionalDetails"]["problemName"]).lstrip()
          status = "NOT RESOLVED"
          resource_name = str(body["data"]["resourceName"]).lstrip()
          user_ocid = str(body["data"]["additionalDetails"]["problemAdditionalDetails"]["User OCID"]).lstrip()
          target_resource_name = str(body["data"]["additionalDetails"]["resourceName"]).lstrip()
          target_resource_id = str(body["data"]["additionalDetails"]["resourceId"]).lstrip()
          risk_level = str(body["data"]["additionalDetails"]["riskLevel"]).lstrip()
          comments = str(body["data"]["additionalDetails"]["problemAdditionalDetails"]["comments"]).lstrip()
          comments_items = comments.split(",")
          additional_details = "\r\r\nAction : Closure comments was not in required format hence, no action by automation."
    
          try:
                # Check Problem Type
                if problem_name == "PASSWORD_TOO_OLD":
                   identity_client.create_or_reset_ui_password(user_id=user_ocid)
                   additional_details = "\r\r\nAction : Your password has been reset by the System Administrator as per password policy rotation. Please set new password by clicking on forgot password from OCI console. "
                   status = "RESOLVED"
    
                elif problem_name == "AUTH_TOKEN_TOO_OLD":
                   auth_secret_ocid = get_secret_ocids(comments_items,"auth_secret_ocid")
                   if auth_secret_ocid != "":
                      # Delete existing auth token
                      identity_client.delete_auth_token(user_id=user_ocid, auth_token_id=target_resource_id)
                      # Create new auth token
                      create_auth_token_response = identity_client.create_auth_token(
                      create_auth_token_details=oci.identity.models.CreateAuthTokenDetails(description=target_resource_name),user_id=user_ocid).data
                      new_value = create_auth_token_response.token
                      # Store new auth token in vault secret
                      update_secret(vault_client,auth_secret_ocid,new_value)
                      additional_details = '\r\nAuth Token - Secret OCID : ' + auth_secret_ocid
                      status = "RESOLVED"
    
                elif problem_name == "SECRET_KEY_TOO_OLD":
                   access_id_secret_ocid = get_secret_ocids(comments_items, "accesskey_secret_ocid")
                   secret_key_secret_ocid = get_secret_ocids(comments_items, "secretkey_secret_ocid")
                   if access_id_secret_ocid != "" and secret_key_secret_ocid != "":
                      # Delete existing customer secrete key
                      delete_secret_key_response = identity_client.delete_customer_secret_key(user_ocid, target_resource_id).data
                      # Create new customer secret key
                      create_customer_secret_key_response = identity_client.create_customer_secret_key(create_customer_secret_key_details=oci.identity.models.CreateCustomerSecretKeyDetails(display_name=target_resource_name),user_id=user_ocid).data
                      new_secret_key = str(create_customer_secret_key_response.key)
                      new_access_key_id = str(create_customer_secret_key_response.id)
                      # Store new customer secret key in vault secret
                      update_secret(vault_client,secret_key_secret_ocid,new_secret_key)
                      update_secret(vault_client,access_id_secret_ocid,new_access_key_id)
                      additional_details = '\r\nAccess Key - Secret OCID : ' + access_id_secret_ocid + \
                               '\r\nSecret Key - Secret OCID : ' + secret_key_secret_ocid
                      status = "RESOLVED"
    
                elif problem_name == "API_KEY_TOO_OLD":
                   key_fingerprint = target_resource_id.split("/")[2]
                   api_secret_ocid = get_secret_ocids(comments_items,"api_secret_ocid")
                   if api_secret_ocid != "":
                      key = RSA.generate(2048)
                      key_private = key.exportKey()
                      pubkey = key.publickey()
                      key_public = pubkey.exportKey()
                      # Delete existing API key
                      delete_api_key_response = identity_client.delete_api_key(user_id=user_ocid,fingerprint=key_fingerprint)
                      # Upload new public API key in OCI for the user
                      upload_api_key_response = identity_client.upload_api_key(user_id=user_ocid,
                                                                               create_api_key_details=oci.identity.models.CreateApiKeyDetails(
                                                                                     key=key_public.decode()))
                      # Store content of new private key in vault secret
                      update_secret(vault_client,api_secret_ocid,key_private.decode())
                      additional_details = '\r\nSecret OCID for private API key : ' + api_secret_ocid
                      status = "RESOLVED"
          except Exception as e:
                additional_details = '\r\r\n Error: '+ str(e)
    
          # Message Body Customization, it can be updated as per need
          line_head = 'Oracle Cloud Notification' + '\n====================='
          message_body = line_head + \
                         '\r\r\nProblem Name : ' + problem_name + \
                         '\r\r\nRisk Level : ' + risk_level + \
                         '\r\nEvent Time : ' + e_time + \
                         '\r\nTenancy Name : ' + t_name + \
                         '\r\nTenancy ID : ' + t_id + \
                         '\r\r\nAdditional Details : ' + '\n-------------------------' \
                         '\r\nResource Name : ' + target_resource_name + \
                         '\r\nResource ID : ' + target_resource_id + \
                         '\r\nResource User OCID : ' + user_ocid + ' ' + additional_details
    
          # Message Title
          message_title = 'Problem : ' + resource_name + ' | ' + status +' by automation '
    
          # Message Detail
          message_details = oci.ons.models.MessageDetails(body=message_body, title=message_title)
    
          # Publish message to ONS
          onsclient.publish_message(ons_topic, message_details)
    
       except (Exception, ValueError) as ex:
          logging.getLogger().info('error parsing json payload: ' + str(ex))
    
       return response.Response(ctx, response_data=json.dumps({"message": "success"}),headers={"Content-Type": "application/json"})
    
  6. Actualice requirements.txt como se muestra a continuación.

    fdk>=0.1.59
    oci
    pycryptodomex
    
  7. Ejecute el siguiente comando para desplegar la función.

    fn -v deploy --app <app-name>
    
    Example: fn -v deploy --app rotatecredapp
    
  8. Ejecute el siguiente comando para agregar la configuración de función para la clave y el valor de configuración.

    • ons_topic: utilice el identificador de Oracle Cloud (OCID) del tema de notificación para recibir notificaciones por correo electrónico.
    fn config function <app-name> <function-name> <config-key> <config-value>
    
    Example: fn config function rotatecredapp rotatecred-func ons_topic ocid1.onstopic.oc1.ap-mumbai-1.aaaaaaaau3onlufcfz.......kae26637zovwd7q
    

Tarea 2: Creación de una Regla de Evento

  1. Vaya a la consola de OCI y haga clic en Observación y gestión.

  2. En Servicio de eventos, haga clic en Reglas y Crear regla.

  3. En la página Crear regla, introduzca el nombre de la regla y la descripción de lo que hace la regla.

  4. En la sección Condiciones de regla, introduzca la siguiente información para especificar el tipo de evento y la acción para disparar la función.

    • Condición: Event Type.
    • Nombre de servicio: Cloud Guard.
    • Tipo de evento: Remediated-Problem.
    • Nombre de Atributo: ProblemRecommendation.
    • Valores de Atributo:
      • Rotate IAM Console password regularly, at least every 90 days.,
      • Rotate IAM Auth token regularly, at least every 90 days.,
      • Rotate IAM Customer secret keys regularly, at least every 90 days.,
      • Rotate API keys regularly, at least every 90 days.

    En la siguiente imagen se muestra un ejemplo del evento de solución de problemas de Oracle Cloud Guard.

    image

Tarea 3: Solución del problema de Oracle Cloud Guard

  1. Vaya a la consola de OCI y haga clic en Identidad y seguridad.

  2. En Cloud Guard, haga clic en Problemas.

  3. Haga clic en uno de los problemas admitidos para la rotación automática.

  4. Haga clic en Marcar como resuelto e introduzca la siguiente información en la sección Comentario según el siguiente formato. Puede agregar información adicional según el proceso de su organización junto con la siguiente información separada por comas (,).

    • La clave secreta de cliente de IAM es demasiado antigua.

      accesskey_secret_ocid:<OCID of access key secret>,secretkey_secret_ocid:<OCID of secret key secret>,<additional comments>

      image

    • La clave de API es demasiado antigua.

      api_secret_ocid:<OCID of api key secret>,<additional comments>

      image

    • El token de autenticación de IAM es demasiado antiguo.

      auth_secret_ocid:<OCID of auth token secret>,<additional comments>

      image

    • La contraseña es demasiado antigua.

      Nota:

      • No hay información necesaria para incluir en los comentarios de este problema.
      • El usuario individual debe restablecer la contraseña haciendo clic en Olvidé la contraseña en la siguiente conexión. El usuario debe tener una dirección de correo electrónico válida para recibir notificaciones de correo electrónico.

Tarea 4: Validación de una nueva credencial de OCI IAM y notificación por correo electrónico

Recibirá una notificación por correo electrónico de resolución de problemas con detalles del OCID secreto rotado e información adicional.

image

Agradecimientos

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.