주:
- 이 자습서에서는 Oracle Cloud에 액세스해야 합니다. 무료 계정에 등록하려면 Oracle Cloud Infrastructure Free Tier 시작하기를 참조하십시오.
- Oracle Cloud Infrastructure 자격 증명, 테넌시 및 구획에 예제 값을 사용합니다. 실습을 완료했으면 이러한 값을 자신의 클라우드 환경과 관련된 값으로 대체하십시오.
Oracle Cloud Infrastructure Functions를 사용하여 이메일을 통해 Oracle Cloud Guard 문제 전송
소개
오늘날 업계 전반의 사이버 보안 팀은 클라우드 환경의 역동적인 특성을 다루는 동시에 견고한 보안 상태를 유지하는 복잡한 과제에 직면하고 있습니다. 수많은 리소스, 구성 및 진화하는 위협으로 인해 문제를 신속하게 추적하고 해결하는 것이 중요합니다. Oracle은 조직이 보안 관리를 간소화하여 이러한 당면 과제를 해결할 수 있는 도구를 갖추는 것의 중요성을 인식하고 있습니다. Oracle Cloud Guard는 기업의 클라우드 보안 관리 간소화를 지원하는 강력한 기능을 제공합니다. 취약점을 식별하는 것에서 팀 간 문제를 자동으로 배포하여 시기적절하게 해결할 수 있습니다.
이 사용지침서에서는 보안 팀이 이메일을 통해 직접 자세한 Oracle Cloud Guard 보안 보고서를 수신하고 공유할 수 있도록 해주는 OCI의 네이티브 서비스를 활용하는 자동 솔루션에 대해 간략하게 설명합니다. 이 접근 방식은 수동 개입을 줄이고, 지속적인 모니터링을 촉진하고, 클라우드 보안에 대한 사전 예방적 입지를 보장합니다.
목표
- 모든 Oracle Cloud Guard 미결 문제를 적절한 팀에 배포할 수 있는 이메일로 받아 해결 경로를 간소화합니다.
필요 조건
-
OCI(Oracle Cloud Infrastructure) 테넌시에 액세스합니다.
-
Oracle Cloud Guard, OCI Functions, OCI Email Delivery 서비스, OCI Vault 및 OCI Resource Scheduler를 관리할 수 있는 권한입니다.
작업 1: 필요한 정책 및 Oracle Cloud Infrastructure Identity and Access Management(OCI IAM) 권한 설정
이 솔루션의 각 구성 요소에는 상호 작용하는 OCI 리소스에 대한 액세스 권한이 있어야 합니다.
-
리소스 스케줄러 정책: 스케줄러가 정의된 일정에 따라 함수를 실행할 수 있도록 허용합니다. 자세한 내용은 예제 정책을 참조하십시오.
-
기능 정책: OCI Vault에서 암호를 읽고 Oracle Cloud Guard 문제를 검색할 수 있는 권한을 함수에 부여합니다. 자세한 내용은 함수에 대한 세부 정보를 참조하십시오.
작업 2: OCI 전자메일 전달 서비스 구성
-
보고서를 전송하는 데 사용할 승인된 발신자 전자메일 주소를 생성하여 OCI 전자메일 전송 서비스를 설정합니다. 자세한 내용은 승인된 발신자 생성을 참조하십시오.
-
제한된 SMTP 액세스 권한을 가진 전용 사용자를 생성하여 전자메일 계정에 대한 SMTP(Simple Mail Transfer Protocol) 인증서를 생성합니다.
-
OCI IAM 사용자를 생성합니다. 자세한 내용은 사용자 생성을 참조하십시오.
-
사용자 기능을 편집하려면 Editing a User's Capabilities을 참조하십시오.
-
SMTP 인증서를 만들려면 Creating SMTP Credentials를 참조하십시오.
-
작업 3: OCI 저장소에 SMTP 인증서 저장
OCI Vault를 사용하여 SMTP 자격 증명을 안전하게 저장합니다. 이렇게 하면 중요한 정보를 기능 외부에 보관하여 추가적인 보안 계층이 추가됩니다.
-
OCI Vault를 설정합니다. 자세한 내용은 Creating a Vault를 참조하십시오.
-
마스터 암호화 키를 만들려면 Creating a Master Encryption Key를 참조하십시오.
-
암호를 만들려면 저장소에서 암호 만들기를 참조하십시오.
작업 4: 함수 개발 및 배치
이 기능은 지난 해에 감지된 해결되지 않은 보안 상태 문제를 인출합니다. 리스크 레벨 및 감지 시간과 같은 매개변수를 기반으로 데이터를 구조화된 보고서로 형식 지정한 후 전자메일을 통해 CSV(쉼표로 구분된 값) 첨부 파일로 전송합니다. 자세한 내용은 함수 배치를 참조하십시오.
다음은 핵심 기능 단계에 대한 개요입니다.
- Oracle Cloud Guard에서 해결되지 않은 문제를 검색합니다.
- 심각도에 따라 문제를 구성하고 형식을 지정합니다.
- CSV 보고서를 생성하고 보고서의 형식을 지정합니다.
- 저장소에서 SMTP 인증서를 검색합니다.
- CSV를 첨부 파일로 사용하여 지정된 수신자에게 전자메일을 전송합니다.
OCI의 서버리스 기능 기능을 사용하여 이 보고서를 사용자 정의하여 사이버 보안 팀의 중요한 보안 영역에 대한 명확성을 극대화할 수 있습니다.
-
func.py
:import oci import io import smtplib import logging import base64 from oci.pagination import list_call_get_all_results from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders from email.mime.text import MIMEText from openpyxl import Workbook from datetime import datetime, timedelta, timezone from openpyxl.styles import Font # Retrieve secrets from OCI Vault def get_secret_value(secret_ocid): print(f"Retrieving secret for OCID: {secret_ocid}") signer = oci.auth.signers.get_resource_principals_signer() secrets_client = oci.secrets.SecretsClient({}, signer=signer) try: secret_content = secrets_client.get_secret_bundle(secret_ocid) secret_data = secret_content.data.secret_bundle_content.content secret_value = base64.b64decode(secret_data).decode('utf-8') return secret_value except Exception as e: print(f"Failed to retrieve secret: {e}") raise # Format the CSV def get_font_style(risk_level, time_condition): color_map = { "CRITICAL": "8B0000", "HIGH": "FF8C00", "MEDIUM": "006400", "LOW": "00008B", "MINOR": "000000" } font_color = color_map.get(risk_level, "000000") is_bold = time_condition return Font(color=font_color, bold=is_bold) def get_clients_with_resource_principal(): signer = oci.auth.signers.get_resource_principals_signer() cloud_guard_client = oci.cloud_guard.CloudGuardClient({}, signer=signer) return cloud_guard_client def send_email_via_oci(subject, body, email, attachment, username_secret_ocid, password_secret_ocid, from_email, smtp_endpoint, smtp_port): msg = MIMEMultipart() msg['Subject'] = subject msg['From'] = from_email msg['To'] = email msg.attach(MIMEText(body, 'plain')) today_date = datetime.today().strftime('%Y-%m-%d') filename = f"CloudGuardReport_{today_date}.xlsx" part = MIMEBase('application', "octet-stream") part.set_payload(attachment) encoders.encode_base64(part) part.add_header('Content-Disposition', f"attachment; filename={filename}") msg.attach(part) try: username = get_secret_value(username_secret_ocid) password = get_secret_value(password_secret_ocid) server = smtplib.SMTP(smtp_endpoint, smtp_port) server.starttls() server.login(username, password) server.sendmail(msg['From'], [msg['To']], msg.as_string()) server.quit() print("Email sent successfully.") except Exception as e: print(f"Failed to send email: {e}") raise def handler(ctx, data: io.BytesIO=None): try: cfg = ctx.Config() compartment_id = cfg["compartment-id"] from_email = cfg["from-email"] email = cfg["to-email"] smtp_endpoint = cfg["smtp-endpoint"] smtp_port = cfg["smtp-port"] username_secret_ocid = cfg["smtp-username-secret-ocid"] password_secret_ocid = cfg["smtp-password-secret-ocid"] cg_access_level = cfg["cloudguard-access-level"] cloud_guard_client = get_clients_with_resource_principal() current_time = datetime.now(timezone.utc) time_last_7_days = current_time - timedelta(days=7) formatted_time_one_year_ago = (current_time - timedelta(days=365)).strftime("%Y-%m-%dT%H:%M:%S.%fZ") formatted_time_last_7_days = time_last_7_days.strftime("%Y-%m-%dT%H:%M:%S.%fZ") # List problems problem_response = list_call_get_all_results( cloud_guard_client.list_problems, compartment_id, compartment_id_in_subtree=True, access_level=cg_access_level, time_first_detected_greater_than_or_equal_to=formatted_time_one_year_ago, time_last_detected_greater_than_or_equal_to=formatted_time_last_7_days ).data if not problem_response: logging.info("No open problems found.") return {"statusCode": 200, "body": "No open problems found."} print(f"Found {len(problem_response)} problems") # Sort problems by Risk Level risk_level_order = {"CRITICAL": 1, "HIGH": 2, "MEDIUM": 3, "LOW": 4, "MINOR": 5} problem_response.sort(key=lambda x: risk_level_order.get(x.risk_level, 6)) # Create a workbook and select active worksheet wb = Workbook() ws = wb.active ws.title = "Cloud Guard Problems" ws.append([ "Region", "ID", "Resource Type", "Resource Name", "Risk Level", "Detector", "Rule Display Name", "Rule Description", "Rule Recommendation", "Resource ID", "Time First Detected", "Time Last Detected" ]) # Iterate through the problems for problem in problem_response: try: detector_rule_response = cloud_guard_client.get_detector_rule(problem.detector_id, problem.detector_rule_id).data rule_description = detector_rule_response.description detector = detector_rule_response.detector rule_display_name = detector_rule_response.display_name rule_recommendation = detector_rule_response.recommendation except Exception as e: logging.error(f"Error fetching detector rule details for problem {problem.id}: {str(e)}") rule_description, detector, rule_display_name, rule_recommendation = "N/A", "N/A", "N/A", "N/A" problem_details = [ problem.region, problem.id, problem.resource_type, problem.resource_name, problem.risk_level, detector, rule_display_name, rule_description, rule_recommendation, problem.resource_id, problem.time_first_detected.replace(tzinfo=None) if problem.time_first_detected else None, problem.time_last_detected.replace(tzinfo=None) if problem.time_last_detected else None ] # Add row to worksheet ws.append(problem_details) # Apply format time_condition = problem.time_last_detected > problem.time_first_detected if problem.time_last_detected and problem.time_first_detected else False font_style = get_font_style(problem.risk_level, time_condition) row_number = ws.max_row for cell in ws[row_number]: cell.font = font_style virtual_workbook = io.BytesIO() wb.save(virtual_workbook) virtual_workbook.seek(0) # Send email send_email_via_oci("OCI Cloud Guard Report", "Find attached the OCI Cloud Guard Report.", email, virtual_workbook.getvalue(), username_secret_ocid, password_secret_ocid, from_email, smtp_endpoint, smtp_port) return {"statusCode": 200, "body": "Email sent successfully."} except Exception as e: logging.error(f"Error: {str(e)}") return {"statusCode": 500, "body": f"Error: {str(e)}"}
-
func.yaml
:schema_version: 20180708 name: oci-cloud-guard-problems version: 0.0.1 runtime: python build_image: fnproject/python:3.9-dev run_image: fnproject/python:3.9 entrypoint: /python/bin/fdk /function/func.py handler memory: 256 config: compartment-id: Provide a compartment ID here to-email: Provide a valid email ID here from-email: Provide the Approved Sender Email ID created in the Email Delivery Service smtp-username-secret-ocid: Provide the SMTP Username Secret OCID smtp-password-secret-ocid: Provide the SMTP Password Secret OCID smtp-endpoint: Provide the SMTP endpoint from the Email Delivery Service smtp-port: 587 cloudguard-access-level: ACCESSIBLE or RESTRICTED
-
requirements.txt
:fdk oci openpyxl
작업 5: OCI 리소스 스케줄러를 사용하여 함수 스케줄링
마지막 작업은 OCI Resource Scheduler를 사용하여 함수 실행을 자동화하는 것입니다. 이 구성은 매주 또는 사용자 정의된 간격으로 실행될 수 있으므로 시기 적절하고 일관된 보안 보고가 가능합니다. 자세한 내용은 스케줄 생성을 참조하십시오.
-
함수를 실행하려면 다음 필수 정보를 입력합니다.
함수를 배치하기 전에 다음 구성 세부 정보를 수집하십시오. 이러한 입력은 배치 방식에 따라 함수 구성 파일(
func.yaml
) 또는 OCI 콘솔에서 직접 제공됩니다.- 구획 ID: Oracle Cloud Guard가 사용으로 설정된 테넌시 ID입니다.
- 보낸 사람 전자메일: OCI Email Delivery 서비스에서 생성한 승인된 발신자 전자메일입니다.
- 전자 우편으로 보내기: 보고서를 보낼 전자 우편 주소입니다.
- SMTP 끝점: 이를 찾으려면 전자메일 전송 및 구성으로 이동하십시오.
- SMTP 포트: OCI Email Delivery 서비스 구성에 지정된 대로 일반적으로 587 또는 25입니다.
- SMTP 사용자 이름 암호 OCID: SMTP 사용자 이름에 대한 OCID로, OCI 저장소에 안전하게 저장됩니다.
- SMTP 비밀번호 암호 OCID: SMTP 비밀번호에 대한 OCID로, OCI 저장소에 안전하게 저장됩니다.
- Cloud Guard 액세스 레벨: 리소스에 대한 액세스 레벨(
ACCESSIBLE
또는RESTRICTED
)을 정의합니다. 기본값은ACCESSIBLE
입니다.
-
실행 가능한 Oracle Cloud Guard 보고서인 샘플 출력이 제공됩니다.
이 Oracle Cloud Guard 보고서는 위험 레벨별로 분류된 OCI 환경의 해결되지 않은 보안 문제에 대한 구조화된 개요를 제공합니다. 지역, 리소스 유형, 심각도 및 감지 타임스탬프와 같은 중요한 세부 정보를 통해 사이버 보안 팀은 작업을 평가하고 우선 순위를 지정할 수 있습니다.
다음 단계
Oracle Cloud Guard의 자동화된 보고는 사이버 보안 팀이 클라우드 보안 위험을 관리하는 간소화되고 사전 예방적인 접근 방식을 제공합니다. 조직은 심각도 및 위험 수준별로 분류된 일회성 구성으로 해결되지 않은 보안 문제에 대한 주간 보고서를 받을 수 있습니다. 이 솔루션은 클라우드 보안 관리의 복잡한 수동 작업을 해결하여 팀이 문제를 추적하는 대신 적시에 문제를 해결하는 데 집중할 수 있도록 합니다. Oracle Cloud Guard 및 CNAPP 기능 사용에 대한 자세한 내용은 Oracle 담당자에게 문의하거나 Cloud Security Services를 참조하십시오.
확인
- 작성자 - Aneel Kanuri(Distinguished Cloud Architect)
추가 학습 자원
docs.oracle.com/learn에서 다른 실습을 탐색하거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하세요. 또한 Oracle Learning Explorer가 되려면 education.oracle.com/learning-explorer을 방문하십시오.
제품 설명서는 Oracle Help Center를 참조하십시오.
Send Oracle Cloud Guard Problems through Email using Oracle Cloud Infrastructure Functions
G23225-01
December 2024