浏览代码

AMBARI-25391: Ambari logging Grafana Password in ActionQueue.py (#3497)

Zhiguo Wu 3 年之前
父节点
当前提交
d1cb2cb025

+ 10 - 2
ambari-agent/src/main/python/ambari_agent/ActionQueue.py

@@ -25,6 +25,7 @@ import os
 import ambari_simplejson as json
 import time
 import signal
+import re
 
 from AgentException import AgentException
 from ambari_agent.BackgroundCommandExecutionHandle import BackgroundCommandExecutionHandle
@@ -37,6 +38,13 @@ installScriptHash = -1
 
 MAX_SYMBOLS_PER_LOG_MESSAGE = 7900
 
+PASSWORD_REPLACEMENT = '[PROTECTED]'
+PASSWORD_PATTERN = re.compile(r"('\S*password':\s*u?')(\S+)(')")
+
+def hide_passwords(text):
+  """ Replaces the matching passwords with **** in the given text """
+  return None if text is None else PASSWORD_PATTERN.sub(r'\1{}\3'.format(PASSWORD_REPLACEMENT), text)
+
 
 class ActionQueue(threading.Thread):
   """ Action Queue for the agent. We pick one command at a time from the queue
@@ -393,12 +401,12 @@ class ActionQueue(threading.Thread):
     If logs are redirected to syslog (syslog_enabled=1), this is very useful for logging big messages.
     As syslog usually truncates long messages.
     """
-    chunks = split_on_chunks(text, MAX_SYMBOLS_PER_LOG_MESSAGE)
+    chunks = split_on_chunks(hide_passwords(text), MAX_SYMBOLS_PER_LOG_MESSAGE)
     if len(chunks) > 1:
       for i in range(len(chunks)):
         logger.info("Cmd log for taskId={0} and chunk {1}/{2} of log for command: \n".format(taskId, i+1, len(chunks)) + chunks[i])
     else:
-      logger.info("Cmd log for taskId={0}: ".format(taskId) + text)
+      logger.info("Cmd log for taskId={0}: ".format(taskId) + chunks[0])
 
   def get_retry_delay(self, last_delay):
     """

+ 17 - 1
ambari-agent/src/test/python/ambari_agent/TestActionQueue.py

@@ -21,7 +21,7 @@ from Queue import Queue
 
 from unittest import TestCase
 from ambari_agent.LiveStatus import LiveStatus
-from ambari_agent.ActionQueue import ActionQueue
+from ambari_agent.ActionQueue import ActionQueue, hide_passwords
 from ambari_agent.AmbariConfig import AmbariConfig
 import os, errno, time, pprint, tempfile, threading
 import sys
@@ -1167,6 +1167,22 @@ class TestActionQueue(TestCase):
     },
   }
 
+  def test_hide_passwords_no_matching_password(self):
+    self.assertEqual(hide_passwords(None), None)
+    self.assertEqual(hide_passwords('No password in this text'), 'No password in this text')
+    self.assertEqual(hide_passwords("No 'password' 'in' this text'"), "No 'password' 'in' this text'")
+    self.assertEqual(hide_passwords("No 'password': in this text"), "No 'password': in this text")
+    self.assertEqual(hide_passwords("No u'password': u'' in this text"), "No u'password': u'' in this text")
+
+  def test_hide_passwords(self):
+    self.assertEqual(hide_passwords("u'password': u'changeIT!'"), "u'password': u'[PROTECTED]'")
+    self.assertEqual(hide_passwords("'password': 'password'"), "'password': '[PROTECTED]'")
+    self.assertEqual(hide_passwords("'some.password': 'password', 'other.password': 'password',"), "'some.password': '[PROTECTED]', 'other.password': '[PROTECTED]',")
+    self.assertEqual(hide_passwords("u'metrics_grafana_password': u'mypassword123!'"), "u'metrics_grafana_password': u'[PROTECTED]'")
+
+    self.assertEqual(hide_passwords("u'metrics_grafana_username': u'admin', u'metrics_grafana_password': u'mypassword123!', some text, u'clientssl.keystore.password': u'myKeyFilePassword', another text, "),
+                     "u'metrics_grafana_username': u'admin', u'metrics_grafana_password': u'[PROTECTED]', some text, u'clientssl.keystore.password': u'[PROTECTED]', another text, ")
+
 def patch_output_file(pythonExecutor):
   def windows_py(command, tmpout, tmperr):
     proc = MagicMock()