Remarques :

Activation de la rotation automatique des informations d'identification Oracle Cloud Infrastructure Identity and Access Management

Introduction

Ce tutoriel permet de faire pivoter automatiquement les informations d'identification Oracle Cloud Infrastructure Identity and Access Management (OCI IAM) qui sont la clé d'API, le jeton d'authentification, les clés secrètes client et les mots de passe de connexion à la console OCI. Il est basé sur la résolution des problèmes Oracle Cloud Guard et sur le service OCI Notifications. Il comble également l'écart des règles de répondeur par défaut pour effectuer la rotation des informations d'identification OCI IAM.

Oracle Cloud Guard détecte les problèmes en fonction des règles définies dans les stratégies. Une fois qu'une règle est satisfaite, elle crée un problème.

Il s'agit d'une meilleure pratique en matière de sécurité et recommandée par le banc d'essai du Center for Internet Security Oracle Cloud Infrastructure Foundations (CIS OCI Foundations) pour effectuer la rotation des informations d'identification tous les 90 jours.

Remarque : cette solution a été testée pour un domaine d'identité par défaut.

Objectifs

Prérequis

L'administrateur OCI IAM doit créer les éléments suivants :

Tâche 1 : créer et déployer des fonctions OCI

  1. Connectez-vous à la console OCI et cliquez sur Cloud Shell dans la barre de navigation supérieure.

    Remarque : vous pouvez également utiliser votre propre outil IDE pour créer et déployer une fonction.

  2. Créez une fonction à l'aide de l'interface de ligne de commande du projet Fn à partir de cloud shell. Pour plus d'informations, reportez-vous à Création, déploiement et appel d'une fonction HelloWorld.

    fn init --runtime python <function-name>
    
    Example: fn init --runtime python rotatecred-func
    
  3. Passez au répertoire que vous venez de créer.

  4. Créez une application pour déployer la fonction à l'aide de la commande suivante.

    # 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. Copiez et collez le script suivant dans func.py en écrasant le contenu existant.

    # 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. Mettez à jour requirements.txt comme indiqué ci-dessous.

    fdk>=0.1.59
    oci
    pycryptodomex
    
  7. Exécutez la commande suivante pour déployer la fonction.

    fn -v deploy --app <app-name>
    
    Example: fn -v deploy --app rotatecredapp
    
  8. Exécutez la commande suivante pour ajouter une configuration de fonction pour la clé et la valeur de configuration.

    • ons_topic : utilisez l'identificateur Oracle Cloud (OCID) du sujet de notification pour recevoir la notification par courriel.
    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
    

Tâche 2 : créer une règle d'événement

  1. Accédez à la console OCI et cliquez sur Observation et gestion.

  2. Sous Service d'événements, cliquez sur Règles et Créer une règle.

  3. Sur la page Créer une règle, entrez le nom de la règle et la description de l'action de la règle.

  4. Dans la section Conditions de règle, entrez les informations suivantes pour indiquer le type d'événement et l'action à déclencher pour la fonction.

    • Configuration : Event Type.
    • Nom de service : Cloud Guard.
    • Type d'événement : Remediated-Problem.
    • Nom d'attribut : ProblemRecommendation.
    • Valeurs d'attribut :
      • 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'image suivante est un exemple d'événement de résolution de problème Oracle Cloud Guard.

    image

Tâche 3 : résoudre le problème lié à Oracle Cloud Guard

  1. Accédez à la console OCI et cliquez sur Identité et sécurité.

  2. Sous Cloud Guard, cliquez sur Problèmes.

  3. Cliquez sur l'un des problèmes pris en charge pour la rotation automatique.

  4. Cliquez sur Marquer comme résolu et entrez les informations suivantes dans la section Commentaire selon le format suivant. Vous pouvez ajouter des informations supplémentaires conformément au processus de votre organisation, ainsi que les informations suivantes, séparées par des virgules (,).

    • La clé secrète client IAM est trop ancienne.

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

      image

    • La clé d'API est trop ancienne.

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

      image

    • Le jeton d'authentification IAM est trop ancien.

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

      image

    • Le mot de passe est trop ancien.

      Remarque :

      • Aucune information requise à inclure dans les commentaires pour ce problème.
      • Le mot de passe doit être réinitialisé par l'utilisateur individuel en cliquant sur Mot de passe oublié lors de la prochaine connexion. L'utilisateur doit disposer d'une adresse électronique valide pour recevoir les notifications par courriel.

Tâche 4 : validation des nouvelles informations d'identification OCI IAM et notification par courriel

Vous recevrez un courriel de résolution des problèmes avec des détails sur l'OCID de clé secrète faisant l'objet d'une rotation et des informations supplémentaires.

image

Remerciements

Ressources de formation supplémentaires

Parcourez d'autres ateliers sur docs.oracle.com/learn ou accédez à davantage de contenus de formation gratuits sur le canal Oracle Learning YouTube. De plus, rendez-vous sur education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.

Pour obtenir de la documentation sur le produit, visitez Oracle Help Center.