Hinweis:
- Dieses Tutorial erfordert Zugriff auf Oracle Cloud. Informationen zum Registrieren eines kostenlosen Accounts finden Sie unter Erste Schritte mit Oracle Cloud Infrastructure Free Tier.
- Es verwendet Beispielwerte für Oracle Cloud Infrastructure-Zugangsdaten, -Mandanten und -Compartments. Wenn Sie Ihre Übung abgeschlossen haben, ersetzen Sie diese Werte durch spezifische Werte für Ihre Cloud-Umgebung.
Automatische Rotation von Oracle Cloud Infrastructure Identity and Access Management-Zugangsdaten aktivieren
Einführung
In diesem Tutorial können Sie Oracle Cloud Infrastructure Identity and Access Management-(OCI IAM-)Zugangsdaten automatisch rotieren, die API-Schlüssel, Authentifizierungstoken, Kunden-Secret-Keys und Anmeldekennwörter der OCI-Konsole sind. Sie basiert auf der Problembehebung mit Oracle Cloud Guard und dem OCI Notifications-Service. Außerdem erfüllt es die Lücke der Standard-Responder-Regeln zum Rotieren der OCI-IAM-Zugangsdaten.
Oracle Cloud Guard erkennt Probleme basierend auf Regeln, die in den Policys definiert sind. Sobald eine Regel erfüllt ist, entsteht ein Problem.
Es ist eine Best Practice zur Sicherheit und wird von der Center for Internet Security Oracle Cloud Infrastructure Foundations (CIS OCI Foundations)-Benchmark empfohlen, die Zugangsdaten alle 90 Tage zu rotieren.
Hinweis: Diese Lösung wurde für eine Standardidentitätsdomain getestet.
Ziele
-
Rotieren Sie das Oracle Cloud Infrastructure-(OCI-)Authentifizierungstoken, den API-Schlüssel, den Kunden-Secret-Key und das Kennwort der OCI-Konsole durch Automatisierung, indem Sie das Oracle Cloud Guard-Problem beheben. Die folgenden Oracle Cloud Guard-Probleme werden für die automatische Rotation von OCI IAM-Zugangsdaten verwendet.
- API-Schlüssel ist zu alt
- IAM-Authentifizierungstoken ist zu alt
- IAM-Customer Secret-Schlüssel ist zu alt
- Kennwort ist zu alt
Voraussetzungen
OCI-IAM-Administrator muss Folgendes erstellen:
-
Dynamische Gruppe und Policys für OCI Functions, um Probleme aufzurufen, zu beheben und E-Mail-Benachrichtigungen zu senden.
-
Dynamische Gruppe: Erstellen Sie eine dynamische Gruppe für das Funktions-Compartment. Weitere Informationen finden Sie unter Dynamische Gruppe erstellen
# Replace OCID for function compartment All {resource.type = 'fnfunc', resource.compartment.id = '<function-compartment>'} Example: All {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaaaanovmfmmnonjjyxeq4jyghszj2eczlrkgj5svnxrt...'}
-
Policys: Erstellen Sie Policys, um der Funktion eine dynamische Gruppe zuzuweisen. Weitere Informationen finden Sie unter Erste Schritte mit Policys.
# Replace dynamic-group-name, function-compartment and OCID of vault secret for OCI function Allow dynamic-group <dynamic-group-name> to inspect compartments in tenancy Allow dynamic-group <dynamic-group-name> to inspect users in tenancy Allow dynamic-group <dynamic-group-name> to manage users in tenancy where any {request.permission = 'USER_UPDATE', request.permission = 'USER_AUTHTOKEN_SET', request.permission = 'USER_AUTHTOKEN_REMOVE', request.permission = 'USER_SECRETKEY_ADD', request.permission = 'USER_SECRETKEY_REMOVE', request.permission = 'USER_UIPASS_SET', request.permission = 'USER_APIKEY_ADD', request.permission = 'USER_APIKEY_REMOVE'} Allow dynamic-group <dynamic-group-name> to read repos in compartment <function-compartment> Allow dynamic-group <dynamic-group-name> to use secret-family in compartment <vault-compartment> where target.secret.id='<ocid of OCI vault secret to store rotated OCI secrets>' Allow dynamic-group <dynamic-group-name> to use ons-topics in tenancy
-
-
Compartment, Gruppe und Policys für Entwickler, um Secrets zu erstellen und die Funktion bereitzustellen.
# Replace group-name as per your tenancy Allow group <group-name> to manage repos in compartment <function-compartment> Allow group <group-name> to manage vaults in compartment <function-compartment> Allow group <group-name> to manage keys in compartment <function-compartment> Allow group <group-name> to manage secret-family in compartment <function-compartment> Allow group <group-name> to manage functions-family in compartment <function-compartment> Allow group <group-name> to use cloud-shell in tenancy Allow group <group-name> to use virtual-network-family in compartment <network-compartment> Allow group <group-name> to read objectstorage-namespaces in tenancy
-
OCI-Benachrichtigungsthema für das SecOps-Team, um E-Mail-Benachrichtigungen zu erhalten.
-
Oracle Cloud Infrastructure Secrets in Vault zum Speichern von rotierten OCI IAM-Zugangsdaten, die durch Automatisierung erstellt wurden.
Hinweis: Stellen Sie sicher, dass Sie vorhandene OCI IAM-Zugangsdaten für Oracle Cloud Infrastructure Secrets in Vault kopiert haben, bevor Sie diese Automatisierung zum ersten Mal ausführen.
Aufgabe 1: OCI-Funktionen erstellen und bereitstellen
-
Melden Sie sich bei der OCI-Konsole an, und klicken Sie in der oberen Navigation auf Cloud Shell.
Hinweis: Sie können auch ein eigenes IDE-Tool verwenden, um eine Funktion zu erstellen und bereitzustellen.
-
Erstellen Sie eine Funktion mit der Fn-Projekt-CLI aus der cloud shell. Weitere Informationen finden Sie unter Hloworld-Funktion erstellen, bereitstellen und aufrufen.
fn init --runtime python <function-name> Example: fn init --runtime python rotatecred-func
-
Ändern Sie das Verzeichnis in das neu erstellte Verzeichnis.
-
Erstellen Sie eine App, um die Funktion mit dem folgenden Befehl bereitzustellen.
# 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....."]'
-
Kopieren Sie das folgende Skript, und fügen Sie es in die Datei
func.py
ein, indem Sie den vorhandenen Inhalt überschreiben.# 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"})
-
Aktualisieren Sie
requirements.txt
wie unten gezeigt.fdk>=0.1.59 oci pycryptodomex
-
Führen Sie den folgenden Befehl aus, um die Funktion bereitzustellen.
fn -v deploy --app <app-name> Example: fn -v deploy --app rotatecredapp
-
Führen Sie den folgenden Befehl aus, um die Funktionskonfiguration für Konfigurationsschlüssel und -wert hinzuzufügen.
ons_topic
: Verwenden Sie die Oracle Cloud-ID (OCID) des Benachrichtigungsthemas für den Empfang von E-Mail-Benachrichtigungen.
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
Aufgabe 2: Ereignisregeln erstellen
-
Gehen Sie zur OCI-Konsole, und klicken Sie auf Observability and Management.
-
Klicken Sie im Events-Serviceauf Regeln und Regel erstellen.
-
Geben Sie auf der Seite Regel erstellen den Namen für die Regel und die Beschreibung der jeweiligen Regel ein.
-
Geben Sie im Abschnitt Regelbedingungen die folgenden Informationen ein, um den Ereignistyp und die Aktion zum Auslösen der Funktion anzugeben.
- Bedingung:
Event Type
. - Service-Name:
Cloud Guard
. - Ereignistyp:
Remediated-Problem
. - Attributname:
ProblemRecommendation
. - Attributwerte:
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
.
Das folgende Image ist ein Beispiel für ein Problembehebungsereignis von Oracle Cloud Guard.
- Bedingung:
Aufgabe 3: Oracle Cloud Guard-Problem beheben
-
Gehen Sie zur OCI-Konsole, und klicken Sie auf Identität und Sicherheit.
-
Klicken Sie unter Cloud Guard auf Probleme.
-
Klicken Sie auf eines der unterstützten Probleme für die automatische Rotation.
-
Klicken Sie auf Als gelöst markieren, und geben Sie die folgenden Informationen im Abschnitt Kommentar entsprechend dem folgenden Format ein. Sie können zusätzliche Informationen gemäß Ihrem Organisationsprozess zusammen mit den folgenden durch Kommas (,) getrennten Informationen hinzufügen.
-
IAM-Customer Secret-Schlüssel ist zu alt.
accesskey_secret_ocid:<OCID of access key secret>,secretkey_secret_ocid:<OCID of secret key secret>,<additional comments>
-
API-Schlüssel ist zu alt.
api_secret_ocid:<OCID of api key secret>,<additional comments>
-
IAM-Authentifizierungstoken ist zu alt.
auth_secret_ocid:<OCID of auth token secret>,<additional comments>
-
Kennwort ist zu alt.
Hinweis:
- Für Kommentare zu diesem Problem sind keine Informationen erforderlich.
- Das Kennwort muss vom einzelnen Benutzer zurückgesetzt werden, indem bei der nächsten Anmeldung auf Kennwort vergessen geklickt wird. Der Benutzer muss über eine gültige E-Mail-Adresse verfügen, um E-Mail-Benachrichtigungen zu erhalten.
-
Aufgabe 4: Neue OCI IAM-Zugangsdaten und E-Mail-Benachrichtigung validieren
Sie erhalten eine E-Mail-Benachrichtigung zur Problemlösung mit Details zur rotierten Secret-OCID und weiteren Informationen.
Verwandte Links
Danksagungen
-
Autor - Dipesh Kumar Rathod (Master Principal Cloud Architect, Infrastruktur)
-
Mitwirkender - Bhanu Prakash Lohumi (Senior Cloud Engineer, Infrastruktur)
Weitere Lernressourcen
Lernen Sie andere Übungen auf docs.oracle.com/learn kennen, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube Channel zu. Außerdem können Sie education.oracle.com/learning-explorer besuchen, um Oracle Learning Explorer zu werden.
Die Produktdokumentation finden Sie im Oracle Help Center.
Enable Auto Rotation of Oracle Cloud Infrastructure Identity and Access Management Credentials
F93262-01
February 2024
Copyright © 2024, Oracle and/or its affiliates.