This is an automated email from the ASF dual-hosted git repository.

pabloem pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new ad39be0f58b Clarify service account key issue reports (#39894)
ad39be0f58b is described below

commit ad39be0f58b3030da2ea126e369bb96b78b472cf
Author: HansMarcus01 <[email protected]>
AuthorDate: Wed Aug 26 14:03:22 2026 -0600

    Clarify service account key issue reports (#39894)
---
 infra/enforcement/README.md       |  4 ++--
 infra/enforcement/account_keys.py |  9 +++++----
 infra/enforcement/sending.py      | 10 ++++++++--
 infra/enforcement/test_sending.py |  6 +++---
 4 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/infra/enforcement/README.md b/infra/enforcement/README.md
index b92e5f7e180..90fc7697475 100644
--- a/infra/enforcement/README.md
+++ b/infra/enforcement/README.md
@@ -138,7 +138,7 @@ The enforcement tools are consolidated into a single daily 
workflow (`.github/wo
 
 This unified workflow executes both security domains sequentially:
 - **IAM Policy Enforcement:** Validates user bindings against the defined 
policies.
-- **Unmanaged Keys Audit:** Detects rogue service account keys generated 
outside the official rotation system.
+- **Unmanaged Keys Audit:** Detects rogue service account keys generated 
outside the official rotation system and reports them to the 
`[IAC_DRIFT_SA_KEY]` issue.
 
 **Note**:
 - **Manual trigger**: The workflow can also be triggered manually via 
`workflow_dispatch`.
@@ -175,7 +175,7 @@ python account_keys.py --action generate
 - **check**: Validates service account keys and their permissions against 
defined policies and reports any differences (default behavior)
 - **announce**: Creates or updates a GitHub issue and sends an email 
notification when service account keys policies differ from the defined ones.
   - For general configuration errors, it updates the main compliance issue.
-  - **For unmanaged/rogue keys (Security Alerts)**, it consolidates alerts 
into a dedicated `[SECURITY]` issue acting as a live dashboard. It updates the 
issue by placing the newest audit report at the top and moving the previous 
reports into a collapsed `<details>` history section. If the keys are revoked 
and the infrastructure becomes healthy, the system automatically resolves and 
closes the issue.
+  - **For unmanaged/rogue keys**, it consolidates alerts into a dedicated 
`[IAC_DRIFT_SA_KEY]` issue acting as a live dashboard. It updates the issue by 
placing the newest audit report at the top and moving the previous reports into 
a collapsed `<details>` history section. If the keys are revoked and the 
infrastructure becomes healthy, the system automatically resolves and closes 
the issue.
 - **print**: Prints announcement details for testing purposes without creating 
actual GitHub issues or sending emails
 - **generate**: Updates the compliance file to match the current GCP service 
account keys and Secret Manager permissions
 
diff --git a/infra/enforcement/account_keys.py 
b/infra/enforcement/account_keys.py
index a1248e3ee09..3c173d2a8af 100644
--- a/infra/enforcement/account_keys.py
+++ b/infra/enforcement/account_keys.py
@@ -28,6 +28,7 @@ from sending import SendingClient
 
 SECRET_MANAGER_LABEL = "beam-infra-secret-manager"
 IAC_DRIFT_SA_KEY = "IAC_DRIFT_SA_KEY"
+ACCOUNT_KEYS_POLICY = "ACCOUNT_KEYS_POLICY"
 
 class AuthorizedUser(TypedDict):
     email: str
@@ -385,8 +386,8 @@ class AccountKeysPolicyComplianceCheck:
 
         if general_issues:
             self.logger.info(f"Found {len(general_issues)} general compliance 
issues. Triggering announcement...")
-            title = f"[{IAC_DRIFT_SA_KEY}] Action Required: Unauthorized 
Service Accounts Detected"
-            body = f"Unauthorized Service Accounts Report\n\n"
+            title = f"[{ACCOUNT_KEYS_POLICY}] Action Required: Service Account 
Policy Drift"
+            body = f"Service Account Policy Drift Report\n\n"
             body += f"Account keys for project {self.project_id} are not 
compliant with the defined policies on {self.service_account_keys_file}\n\n"
             for issue in general_issues:
                 body += f"- {issue}\n"
@@ -423,8 +424,8 @@ class AccountKeysPolicyComplianceCheck:
 
         if general_issues:
             self.logger.info("Printing general compliance announcement...")
-            title = f"[IAC_DRIFT_SA_KEY] Action Required: Unauthorized Service 
Accounts Detected"
-            body = f"Unauthorized Service Accounts Report\n\n"
+            title = f"[{ACCOUNT_KEYS_POLICY}] Action Required: Service Account 
Policy Drift"
+            body = f"Service Account Policy Drift Report\n\n"
             body += f"Account keys for project {self.project_id} are not 
compliant with the defined policies on {self.service_account_keys_file}\n\n"
             for issue in general_issues:
                 body += f"- {issue}\n"
diff --git a/infra/enforcement/sending.py b/infra/enforcement/sending.py
index 9d24a816fbc..67857145aea 100644
--- a/infra/enforcement/sending.py
+++ b/infra/enforcement/sending.py
@@ -228,7 +228,7 @@ class SendingClient:
             self.logger.info("No compliance issues to report to Github.")
             return
 
-        issue_title = "[SECURITY] Action Required: Unmanaged Service Account 
Keys Detected"
+        issue_title = "[IAC_DRIFT_SA_KEY] Action Required: Unmanaged Service 
Account Keys Detected"
         #markdown body
         timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S 
UTC")
         new_report = f"### Unmanaged Keys Audit Report ({timestamp})\n"
@@ -238,6 +238,12 @@ class SendingClient:
             new_report += f"- {issue_text}\n"
 
         new_report += "\n*Please investigate and revoke these keys if they are 
not part of the official rotation system.*"
+        remediation = "\n\n### Remediation\n"
+        remediation += "1. Delete all reported keys as soon as possible.\n"
+        remediation += "2. Replace the deleted keys using the official Beam 
key rotation system. It creates the service account key and registers its key 
ID and private key in the corresponding managed Secret Manager secret 
(`<service-account-id>-key`). Do not create replacement keys manually in IAM.\n"
+        remediation += "3. Run the audit again to confirm that the reported 
keys have been removed and the replacement keys are managed by the rotation 
system.\n"
+        remediation += "\nFor more information, consult 
`infra/keys/README.md`."
+        new_report += remediation
         open_issues = self._get_open_issues(issue_title)
 
         if open_issues:
@@ -272,7 +278,7 @@ class SendingClient:
         Finds any open security issues regarding rogue keys and automatically 
closes them
         if the infrastructure is now healthy.
         """
-        issue_title = "[SECURITY] Action Required: Unmanaged Service Account 
Keys Detected"
+        issue_title = "[IAC_DRIFT_SA_KEY] Action Required: Unmanaged Service 
Account Keys Detected"
         open_issues = self._get_open_issues(issue_title)
         if open_issues:
             target_issue = open_issues[0]
diff --git a/infra/enforcement/test_sending.py 
b/infra/enforcement/test_sending.py
index 26d4080adec..90104e7bb13 100644
--- a/infra/enforcement/test_sending.py
+++ b/infra/enforcement/test_sending.py
@@ -51,7 +51,7 @@ class TestSendingClient(unittest.TestCase):
             "items": [
                 {
                     "number": 1234,
-                    "title": "[SECURITY] Action Required: Unmanaged Service 
Account Keys Detected",
+                    "title": "[IAC_DRIFT_SA_KEY] Action Required: Unmanaged 
Service Account Keys Detected",
                     "body": "Test body",
                     "state": "open",
                     "html_url": "https://github.com/apache/beam/issues/1234";,
@@ -64,7 +64,7 @@ class TestSendingClient(unittest.TestCase):
         mock_request.side_effect = [mock_response_fail, mock_response_success]
 
         # Call get_open_issues
-        issues = self.client._get_open_issues("[SECURITY] Action Required: 
Unmanaged Service Account Keys Detected")
+        issues = self.client._get_open_issues("[IAC_DRIFT_SA_KEY] Action 
Required: Unmanaged Service Account Keys Detected")
         
         # Verify that two requests were made (one retry)
         self.assertEqual(mock_request.call_count, 2)
@@ -79,7 +79,7 @@ class TestSendingClient(unittest.TestCase):
         mock_response.json.return_value = {"items": []}
         mock_request.return_value = mock_response
 
-        title = "[SECURITY] Action Required: Unmanaged Service Account Keys 
Detected"
+        title = "[IAC_DRIFT_SA_KEY] Action Required: Unmanaged Service Account 
Keys Detected"
         self.client._get_open_issues(title)
 
         # Verify that the query parameter was passed correctly to requests

Reply via email to