Browse Source

HUE-586. log files have wrong permission

bc Wong 14 years ago
parent
commit
b25b2cdc9a

+ 61 - 0
desktop/core/src/desktop/lib/daemon_utils.py

@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import grp
+import os
+import pwd
+import desktop.log
+
+def _change_uid_gid(uid, gid=None):
+  """Try to change UID and GID to the provided values.
+  UID and GID are given as integers.
+
+  Src: http://mail.mems-exchange.org/durusmail/quixote-users/4940/1/
+  """
+  if not os.geteuid() == 0:
+    # Do not try to change the gid/uid if not root.
+    return
+  os.setgid(gid)
+  os.setuid(uid)
+
+def get_uid_gid(username, groupname=None):
+  """Try to change UID and GID to the provided values.
+  The parameters are given as names like 'nobody' not integer.
+  May raise KeyError.
+
+  Src: http://mail.mems-exchange.org/durusmail/quixote-users/4940/1/
+  """
+  try:
+    uid, default_grp = pwd.getpwnam(username)[2:4]
+  except:
+    raise KeyError("Couldn't get user id for user %s" % (username,))
+  if groupname is None:
+    gid = default_grp
+  else:
+    try:
+      gid = grp.getgrnam(groupname)[2]
+    except:
+      raise KeyError("Couldn't get group id for group %s" % (groupname,))
+  return (uid, gid)
+
+def drop_privileges_if_necessary(options):
+  if os.geteuid() == 0 and options['server_user'] and options['server_group']:
+    # ensure the that the daemon runs as specified user
+    (uid, gid) = get_uid_gid(options['server_user'], options['server_group'])
+    desktop.log.chown_log_dir(uid, gid)
+    _change_uid_gid(uid, gid)
+

+ 24 - 0
desktop/core/src/desktop/log/__init__.py

@@ -37,6 +37,8 @@ DATE_FORMAT = '%d/%b/%Y %H:%M:%S %z'
 
 CONF_RE = re.compile('%LOG_DIR%|%PROC_NAME%')
 
+_log_dir = None
+
 def _read_log_conf(proc_name, log_dir):
   """
   _read_log_conf(proc_name, log_dir) -> StringIO or None
@@ -71,6 +73,24 @@ def _find_console_stream_handler(logger):
   return None
 
 
+def chown_log_dir(uid, gid):
+  """
+  chown all files in the log dir to this user and group.
+  Should only be called after loggic has been setup.
+  Return success
+  """
+  if _log_dir is None:
+    return False
+  try:
+    os.chown(_log_dir, uid, gid)
+    for entry in os.listdir(_log_dir):
+      os.chown(os.path.join(_log_dir, entry), uid, gid)
+    return True
+  except OSError, ex:
+    print >> sys.stderr, 'Failed to chown log directory %s: ex' % (_log_dir, ex)
+    return False
+
+
 def basic_logging(proc_name, log_dir=None):
   """
   Configure logging for the program ``proc_name``:
@@ -96,6 +116,10 @@ def basic_logging(proc_name, log_dir=None):
       print >> sys.stderr, 'Failed to create log directory "%s": %s' % (log_dir, err)
       raise err
 
+  # Remember where our log directory is
+  global _log_dir
+  _log_dir = log_dir
+
   log_conf = _read_log_conf(proc_name, log_dir)
   if log_conf is not None:
     logging.config.fileConfig(log_conf)

+ 2 - 36
desktop/core/src/desktop/management/commands/runcherrypyserver.py

@@ -16,10 +16,11 @@
 # limitations under the License.
 # a thirdparty project
 
-import sys, os, logging
+import sys, logging
 from django.core.management.base import BaseCommand
 
 from desktop import conf
+from desktop.lib.daemon_utils import drop_privileges_if_necessary
 
 
 CPSERVER_HELP = r"""
@@ -63,41 +64,6 @@ class Command(BaseCommand):
     def usage(self, subcommand):
         return CPSERVER_HELP
 
-def change_uid_gid(uid, gid=None):
-    """Try to change UID and GID to the provided values.
-    UID and GID are given as names like 'nobody' not integer.
-
-    Src: http://mail.mems-exchange.org/durusmail/quixote-users/4940/1/
-    """
-    if not os.geteuid() == 0:
-        # Do not try to change the gid/uid if not root.
-        return
-    (uid, gid) = get_uid_gid(uid, gid)
-    os.setgid(gid)
-    os.setuid(uid)
-
-def get_uid_gid(uid, gid=None):
-    """Try to change UID and GID to the provided values.
-    UID and GID are given as names like 'nobody' not integer.
-
-    Src: http://mail.mems-exchange.org/durusmail/quixote-users/4940/1/
-    """
-    import pwd, grp
-    uid, default_grp = pwd.getpwnam(uid)[2:4]
-    if gid is None:
-        gid = default_grp
-    else:
-        try:
-            gid = grp.getgrnam(gid)[2]            
-        except KeyError:
-            gid = default_grp
-    return (uid, gid)
-
-def drop_privileges_if_necessary(options):
-  if os.geteuid() == 0 and options['server_user'] and options['server_group']:
-    #ensure the that the daemon runs as specified user
-    change_uid_gid(options['server_user'], options['server_group'])
-
 def start_server(options):
     """
     Start CherryPy server

+ 1 - 35
desktop/core/src/desktop/management/commands/runspawningserver.py

@@ -21,6 +21,7 @@ import logging
 from django.core.management.base import BaseCommand
 from desktop import conf
 import spawning.spawning_controller
+from desktop.lib.daemon_utils import drop_privileges_if_necessary
 
 SPAWNING_SERVER_HELP = r"""
   Run Hue using the Spawning WSGI server in asynchronous mode.
@@ -81,41 +82,6 @@ class Command(BaseCommand):
         return SPAWNING_SERVER_HELP
 
 
-def change_uid_gid(uid, gid=None):
-    """Try to change UID and GID to the provided values.
-    UID and GID are given as names like 'nobody' not integer.
-
-    Src: http://mail.mems-exchange.org/durusmail/quixote-users/4940/1/
-    """
-    if not os.geteuid() == 0:
-        # Do not try to change the gid/uid if not root.
-        return
-    (uid, gid) = get_uid_gid(uid, gid)
-    os.setgid(gid)
-    os.setuid(uid)
-
-def get_uid_gid(uid, gid=None):
-    """Try to change UID and GID to the provided values.
-    UID and GID are given as names like 'nobody' not integer.
-
-    Src: http://mail.mems-exchange.org/durusmail/quixote-users/4940/1/
-    """
-    import pwd, grp
-    uid, default_grp = pwd.getpwnam(uid)[2:4]
-    if gid is None:
-        gid = default_grp
-    else:
-        try:
-            gid = grp.getgrnam(gid)[2]
-        except KeyError:
-            gid = default_grp
-    return (uid, gid)
-
-def drop_privileges_if_necessary(options):
-  if os.geteuid() == 0 and options['server_user'] and options['server_group']:
-    # ensure the that the daemon runs as specified user
-    change_uid_gid(options['server_user'], options['server_group'])
-
 def runspawningserver():
   try:
     sock = spawning.spawning_controller.bind_socket(SPAWNING_SERVER_OPTIONS)

+ 19 - 1
desktop/core/src/desktop/supervisor.py

@@ -39,12 +39,12 @@ import os
 import pkg_resources
 import pwd
 import signal
-import string
 import subprocess
 import sys
 import threading
 import time
 
+import desktop.lib.daemon_utils
 import desktop.lib.paths
 import desktop.log
 
@@ -66,6 +66,8 @@ MAX_RESTARTS_IN_WINDOW = 3
 # the drop_root option set to False
 SETUID_USER = "hue"
 SETGID_GROUP = "hue"
+g_user_uid = None       # We figure out the numeric uid/gid later
+g_user_gid = None
 
 # The entry point group in which to find processes to supervise.
 ENTRY_POINT_GROUP = "desktop.supervisor.specs"
@@ -240,6 +242,17 @@ def get_supervisees():
   eps = list(pkg_resources.iter_entry_points(ENTRY_POINT_GROUP))
   return dict((ep.name, ep.load()) for ep in eps)
 
+
+def setup_user_info():
+  """Translate the user/group info into uid/gid."""
+  if os.geteuid() != 0:
+    return
+
+  global g_user_uid, g_user_gid
+  g_user_uid, g_user_gid = \
+      desktop.lib.daemon_utils.get_uid_gid(SETUID_USER, SETGID_GROUP)
+
+
 def drop_privileges():
   """Drop root privileges down to the specified SETUID_USER.
 
@@ -271,9 +284,12 @@ def drop_privileges():
   os.setgid(gr.gr_gid)
   os.setuid(pw.pw_uid)
 
+
 def _init_log(log_dir):
   """Initialize logging configuration"""
   desktop.log.basic_logging(PROC_NAME, log_dir)
+  if os.geteuid() == 0:
+    desktop.log.chown_log_dir(g_user_uid, g_user_gid)
 
 
 def main():
@@ -293,6 +309,8 @@ def main():
   if not os.path.exists(log_dir):
     os.makedirs(log_dir)
 
+  setup_user_info()
+
   pid_file = os.path.abspath(os.path.join(root, options.pid_file))
   pidfile_context = TimeOutPIDLockFile(pid_file, LOCKFILE_TIMEOUT)