Nota

Abilita rotazione automatica delle credenziali di Oracle Cloud Infrastructure Identity and Access Management

Introduzione

Questa esercitazione consente di ruotare automaticamente le credenziali di Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) costituite da chiave API, token di autenticazione, chiavi segrete del cliente e password di login della console OCI. Si basa sulla risoluzione dei problemi di Oracle Cloud Guard e sul servizio di notifiche OCI. Inoltre, colma il divario delle regole del rispondente predefinite per ruotare le credenziali IAM OCI.

Oracle Cloud Guard rileva i problemi in base alle regole definite nei criteri. Una volta soddisfatta, una regola crea un problema.

Si tratta di una best practice per la sicurezza e consigliata dal benchmark The Center for Internet Security Oracle Cloud Infrastructure Foundations (CIS OCI Foundations) per ruotare le credenziali ogni 90 giorni.

Nota: questa soluzione è stata sottoposta a test per un dominio di Identity predefinito.

Obiettivi

Prerequisiti

L'amministratore IAM OCI deve creare:

Task 1: Creare e distribuire le funzioni OCI

  1. Eseguire il login a OCI Console e fare clic su Cloud Shell dalla navigazione superiore.

    Nota: è inoltre possibile utilizzare il proprio strumento IDE per creare e distribuire una funzione.

  2. Creare una funzione utilizzando l'interfaccia CLI del progetto Fn dalla shell cloud shell. Per ulteriori informazioni, vedere Creazione, distribuzione e richiamo di una funzione Helloworld.

    fn init --runtime python <function-name>
    
    Example: fn init --runtime python rotatecred-func
    
  3. Spostarsi nella directory appena creata.

  4. Creare un'applicazione per distribuire la funzione utilizzando il comando seguente.

    # 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. Copiare e incollare il seguente script in func.py sovrascrivendo il contenuto esistente.

    # 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. Aggiornare requirements.txt come mostrato di seguito.

    fdk>=0.1.59
    oci
    pycryptodomex
    
  7. Per distribuire la funzione, eseguire il comando riportato di seguito.

    fn -v deploy --app <app-name>
    
    Example: fn -v deploy --app rotatecredapp
    
  8. Eseguire il comando seguente per aggiungere la configurazione della funzione per chiave e valore di configurazione.

    • ons_topic: utilizzare l'OCID (Oracle Cloud Identifier) dell'argomento di notifica per ricevere la notifica tramite posta elettronica.
    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
    

Task 2: creazione di una regola evento

  1. Andare a OCI Console e fare clic su Osservabilità e gestione.

  2. In Servizio eventi, fare clic su Regole e Crea regola.

  3. Nella pagina Crea regola, inserire il nome della regola e la descrizione delle operazioni eseguite dalla regola.

  4. Nella sezione Condizioni regola, immettere le informazioni riportate di seguito per specificare il tipo di evento e l'azione per attivare la funzione.

    • Condizione: Event Type.
    • Nome servizio: Cloud Guard.
    • Tipo di evento: Remediated-Problem.
    • Nome attributo: ProblemRecommendation.
    • Valori attributi:
      • 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.

    L'immagine seguente mostra un esempio di evento di risoluzione del problema di Oracle Cloud Guard.

    immagine

Task 3: risolvere il problema di Oracle Cloud Guard

  1. Andare a OCI Console e fare clic su Identità e sicurezza.

  2. In Cloud Guard, fare clic su Problemi.

  3. Fare clic su uno dei problemi supportati per la rotazione automatica.

  4. Fare clic su Contrassegna come risolto e immettere le informazioni riportate di seguito nella sezione Commento in base al seguente formato. È possibile aggiungere ulteriori informazioni in base al processo dell'organizzazione insieme alle seguenti informazioni separate da virgole (,).

    • La chiave segreta del cliente IAM è troppo vecchia.

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

      immagine

    • La chiave API è troppo vecchia.

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

      immagine

    • Il token di autenticazione IAM è troppo vecchio.

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

      immagine

    • La password è troppo vecchia.

      Nota:

      • Non sono necessarie informazioni da includere nei commenti per questo problema.
      • La password deve essere reimpostata dal singolo utente facendo clic su Password dimenticata al login successivo. Per ricevere le notifiche e-mail, l'utente deve disporre di un indirizzo e-mail valido.

Task 4: Convalida una nuova credenziale IAM OCI e notifica e-mail

Si riceverà una notifica di posta elettronica di risoluzione dei problemi con i dettagli dell'OCID segreto ruotato e informazioni aggiuntive.

immagine

Conferme

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi a più contenuti gratuiti sulla formazione su Oracle Learning YouTube channel. Inoltre, visita education.oracle.com/learning-explorer per diventare un Oracle Learning Explorer.

Per la documentazione del prodotto, visita l'Oracle Help Center.