You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by sw...@apache.org on 2013/06/22 01:18:59 UTC

svn commit: r1495634 - in /incubator/ambari/trunk/ambari-server: sbin/ambari-server src/main/python/ambari-server.py src/test/python/TestAmbaryServer.py

Author: swagle
Date: Fri Jun 21 23:18:58 2013
New Revision: 1495634

URL: http://svn.apache.org/r1495634
Log:
AMBARI-2463. Missing property and redundant properties in setup ldap flow. (swagle)

Modified:
    incubator/ambari/trunk/ambari-server/sbin/ambari-server
    incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py
    incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py

Modified: incubator/ambari/trunk/ambari-server/sbin/ambari-server
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/sbin/ambari-server?rev=1495634&r1=1495633&r2=1495634&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/sbin/ambari-server (original)
+++ incubator/ambari/trunk/ambari-server/sbin/ambari-server Fri Jun 21 23:18:58 2013
@@ -98,7 +98,7 @@ case "$1" in
         echo -e "Setup ambari-server"
         $PYTHON /usr/sbin/ambari-server.py $@
         ;;
-  setupldap)
+  setup-ldap)
         echo -e "Setting up ldap properties"
         $PYTHON /usr/sbin/ambari-server.py $@
         ;;
@@ -111,7 +111,7 @@ case "$1" in
         $PYTHON /usr/sbin/ambari-server.py $@
         ;;
   *)
-        echo "Usage: /usr/sbin/ambari-server {start|stop|restart|setup|upgrade|status|upgradestack|setupldap|resetmasterkey|setup-https} [options]"
+        echo "Usage: /usr/sbin/ambari-server {start|stop|restart|setup|upgrade|status|upgradestack|setup-ldap|setup-https|resetmasterkey} [options]"
         exit 1
 esac
 

Modified: incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py?rev=1495634&r1=1495633&r2=1495634&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py (original)
+++ incubator/ambari/trunk/ambari-server/src/main/python/ambari-server.py Fri Jun 21 23:18:58 2013
@@ -55,7 +55,7 @@ UPGRADE_STACK_ACTION = "upgradestack"
 UPDATE_METAINFO_ACTION = "update-metainfo"
 STATUS_ACTION = "status"
 SETUP_HTTPS_ACTION = "setup-https"
-LDAP_SETUP_ACTION = "setupldap"
+LDAP_SETUP_ACTION = "setup-ldap"
 RESET_MASTER_KEY_ACTION = "resetmasterkey"
 
 # selinux commands
@@ -164,9 +164,11 @@ SSL_KEY_PASSWORD_FILE_NAME = "pass.txt"
 DEFAULT_SSL_API_PORT = 8443
 
 JDBC_RCA_PASSWORD_ALIAS = "ambari.db.password"
+CLIENT_SECURITY_KEY = "client.security"
+
 LDAP_MGR_PASSWORD_ALIAS = "ambari.ldap.manager.password"
 LDAP_MGR_PASSWORD_PROPERTY = "authentication.ldap.managerPassword"
-
+LDAP_MGR_USERNAME_PROPERTY = "authentication.ldap.managerDn"
 
 AMBARI_CONF_VAR="AMBARI_CONF_DIR"
 AMBARI_SERVER_LIB="AMBARI_SERVER_LIB"
@@ -927,12 +929,17 @@ def read_password(passwordDefault=PG_DEF
 
   password = get_validated_string_input(passwordPrompt, passwordDefault,
                                         passwordPattern, passwordDescr, True)
+
+  if not password:
+    print 'Password cannot be blank.'
+    read_password(passwordDefault, passwordPattern, passwordPrompt, passwordDescr)
+
   if password != passwordDefault:
     password1 = get_validated_string_input("Re-enter password: ",
                                            passwordDefault, passwordPattern, passwordDescr, True)
     if password != password1:
       print "Passwords do not match"
-      password = read_password()
+      password = read_password(passwordDefault, passwordPattern, passwordPrompt, passwordDescr)
 
   return password
 
@@ -2218,8 +2225,9 @@ def get_choice_string_input(prompt,defau
 
 
 
-def get_validated_string_input(prompt, default, pattern, description, is_pass):
-  input =""
+def get_validated_string_input(prompt, default, pattern, description,
+                               is_pass, allowEmpty=True):
+  input = ""
   while not input:
     if SILENT:
       print (prompt)
@@ -2229,88 +2237,132 @@ def get_validated_string_input(prompt, d
     else:
       input = raw_input(prompt)
     if not input.strip():
-      input = default
-      break #done here and picking up default
+      # Empty input - if default available use default
+      if not allowEmpty and not default:
+        print 'Property cannot be blank.'
+        input = ""
+        continue
+      else:
+        input = default
+        break #done here and picking up default
     else:
       if not pattern==None and not re.search(pattern,input.strip()):
         print description
-        input=""
+        input= ""
+
   return input
 
 
-def get_value_from_properties(properties, key):
+def get_value_from_properties(properties, key, default=""):
   try:
-    value = properties[key]
-  except KeyError:
-    return ""
+    value = properties.get_property(key)
+    if not value:
+      value = default
+  except:
+    return default
   return value
 
+def get_prompt_default(defaultStr=None):
+  if not defaultStr or defaultStr == "":
+    return ""
+  else:
+    return '(' + defaultStr + ')'
+
 def setup_ldap():
   properties = get_ambari_properties()
 
   # Setup secure key
   (masterKey, isSecure, isPersisted) = setup_master_key(False)
 
-  LDAP_PRIMARY_URL_DEFAULT = get_value_from_properties(properties,
-    "authentication.ldap.primaryUrl")
-  LDAP_SECONDARY_URL_DEFAULT = get_value_from_properties(properties,
-    "authentication.ldap.secondaryUrl")
-  LDAP_BASE_DN_DEFAULT = get_value_from_properties(properties,
-    "authentication.ldap.baseDn")
-  LDAP_BIND_DEFAULT = get_value_from_properties(properties,
-    "authentication.ldap.bindAnonymously")
-  LDAP_USER_ATT_DEFAULT = get_value_from_properties(properties,
-    "authentication.ldap.usernameAttribute")
-  LDAP_GROUP_BASE_DEFAULT = get_value_from_properties(properties,
-    "authorization.ldap.groupBase")
-  LDAP_GROUP_OBJ_DEFAULT = get_value_from_properties(properties,
-    "authorization.ldap.groupObjectClass")
-  LDAP_GROUP_NAME_DEFAULT = get_value_from_properties(properties,
-    "authorization.ldap.groupNamingAttr")
-  LDAP_GROUP_MEM_DEFAULT = get_value_from_properties(properties,
-    "authorization.ldap.groupMembershipAttr")
-  LDAP_GROUP_MAP_DEFAULT = get_value_from_properties(properties,
-    "authorization.ldap.adminGroupMappingRules")
-  LDAP_GROUP_SEARCH_DEFAULT = get_value_from_properties(properties,
-    "authorization.ldap.groupSearchFilter")
-  LDAP_USER_ROLE_DEFAULT = get_value_from_properties(properties,
-    "authorization.userRoleName")
-  LDAP_ADMIN_ROLE_DEFAULT = get_value_from_properties(properties,
-    "authorization.adminRoleName")
-  LDAP_MGR_DN_DEFAULT = get_value_from_properties(properties,
-    "authentication.ldap.managerDn")
+  # python2.x dict is not ordered
+  ldap_property_list_reqd = ["authentication.ldap.primaryUrl",
+                        "authentication.ldap.secondaryUrl",
+                        "authentication.ldap.useSSL",
+                        "authentication.ldap.usernameAttribute",
+                        "authentication.ldap.baseDn",
+                        "authorization.userRoleName",
+                        "authorization.adminRoleName",
+                        "authentication.ldap.bindAnonymously" ]
+
+  ldap_property_list_opt = [ "authentication.ldap.managerDn",
+                             LDAP_MGR_PASSWORD_PROPERTY ]
+
+  LDAP_PRIMARY_URL_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[0])
+  LDAP_SECONDARY_URL_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[1])
+  LDAP_USE_SSL_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[2], "false")
+  LDAP_USER_ATT_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[3], "uid")
+  LDAP_BASE_DN_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[4])
+  LDAP_USER_ROLE_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[5], "user")
+  LDAP_ADMIN_ROLE_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[6], "admin")
+  LDAP_BIND_DEFAULT = get_value_from_properties(properties, ldap_property_list_reqd[7], "false")
+  LDAP_MGR_DN_DEFAULT = get_value_from_properties(properties, ldap_property_list_opt[0])
 
-  ldap_properties_map =\
+
+  ldap_properties_map_reqd =\
   {
-    "authentication.ldap.primaryUrl":(LDAP_PRIMARY_URL_DEFAULT, "Primary URL: "),\
-    "authentication.ldap.secondaryUrl":(LDAP_SECONDARY_URL_DEFAULT, "Secondary URL: "),\
-    "authentication.ldap.baseDn":(LDAP_BASE_DN_DEFAULT, "Base DN: "),\
-    "authentication.ldap.bindAnonymously":(LDAP_BIND_DEFAULT, "Bind anonymously? [true/alse]?: "),\
-    "authentication.ldap.usernameAttribute":(LDAP_USER_ATT_DEFAULT, "User name attribute uid): "),\
-    "authorization.ldap.groupBase":(LDAP_GROUP_BASE_DEFAULT, "Group base ou=groups,dc=ambari): "),\
-    "authorization.ldap.groupObjectClass":(LDAP_GROUP_OBJ_DEFAULT, "Group object class group): "),\
-    "authorization.ldap.groupNamingAttr":(LDAP_GROUP_NAME_DEFAULT, "Group name attribute cn): "),\
-    "authorization.ldap.groupMembershipAttr":(LDAP_GROUP_MEM_DEFAULT, "Group membership ttribute (member): "),\
-    "authorization.ldap.adminGroupMappingRules":(LDAP_GROUP_MAP_DEFAULT, "Admin group apping rules: "),\
-    "authorization.ldap.groupSearchFilter":(LDAP_GROUP_SEARCH_DEFAULT, "Group search filter: "),\
-    "authorization.userRoleName":(LDAP_USER_ROLE_DEFAULT, "User role name (user): "),\
-    "authorization.adminRoleName":(LDAP_ADMIN_ROLE_DEFAULT, "Admin role name (admin): "),
-    "authentication.ldap.managerDn":(LDAP_MGR_DN_DEFAULT, "Manager DN: ")
+    ldap_property_list_reqd[0]:(LDAP_PRIMARY_URL_DEFAULT, "Primary URL {0}: ".format(get_prompt_default(LDAP_PRIMARY_URL_DEFAULT))),\
+    ldap_property_list_reqd[1]:(LDAP_SECONDARY_URL_DEFAULT, "Secondary URL {0}: ".format(get_prompt_default(LDAP_SECONDARY_URL_DEFAULT))),\
+    ldap_property_list_reqd[2]:(LDAP_USE_SSL_DEFAULT, "Use SSL [true/false] {0}: ".format(get_prompt_default(LDAP_USE_SSL_DEFAULT))),\
+    ldap_property_list_reqd[3]:(LDAP_USER_ATT_DEFAULT, "User name attribute {0}: ".format(get_prompt_default(LDAP_USER_ATT_DEFAULT))),\
+    ldap_property_list_reqd[4]:(LDAP_BASE_DN_DEFAULT, "Base DN {0}: ".format(get_prompt_default(LDAP_BASE_DN_DEFAULT))),\
+    ldap_property_list_reqd[5]:(LDAP_USER_ROLE_DEFAULT, "User role name {0}: ".format(get_prompt_default(LDAP_USER_ROLE_DEFAULT))),\
+    ldap_property_list_reqd[6]:(LDAP_ADMIN_ROLE_DEFAULT, "Admin role name {0}: ".format(get_prompt_default(LDAP_ADMIN_ROLE_DEFAULT))),\
+    ldap_property_list_reqd[7]:(LDAP_BIND_DEFAULT, "Bind anonymously [true/false] {0}: ".format(get_prompt_default(LDAP_BIND_DEFAULT))),\
   }
+
   print "Input LDAP properties. Hit [Enter] to skip property."
   ldap_property_value_map = {}
-  for key in ldap_properties_map.keys():
-    input = get_validated_string_input(ldap_properties_map[key][1],
-      ldap_properties_map[key][0], ".*", "", False)
+  for key in ldap_property_list_reqd:
+    input = get_validated_string_input(ldap_properties_map_reqd[key][1],
+      ldap_properties_map_reqd[key][0], ".*", "", False, False)
     if input is not None and input != "":
       ldap_property_value_map[key] = input
 
-  ldap_property_value_map[LDAP_MGR_PASSWORD_PROPERTY] =\
-  configure_ldap_password(isSecure, masterKey)
-  # Persisting values
-  update_properties(ldap_property_value_map)
+  bindAnonymously = ldap_property_value_map["authentication.ldap.bindAnonymously"]
+  # Ask for manager credentials only if bindAnonymously is true
+  if bindAnonymously and bindAnonymously == 'true' or \
+        bindAnonymously == 'TRUE' or bindAnonymously == 'True':
+    username = get_validated_string_input("Manager DN {0}:".format(
+      get_prompt_default(LDAP_MGR_DN_DEFAULT)), LDAP_MGR_DN_DEFAULT, ".*", "", False, False)
+    ldap_property_value_map[LDAP_MGR_USERNAME_PROPERTY] = username
+    password = configure_ldap_password()
+    if isSecure:
+      ldap_property_value_map[LDAP_MGR_PASSWORD_PROPERTY] = get_alias_string(
+        LDAP_MGR_PASSWORD_ALIAS)
+    else:
+      ldap_property_value_map[LDAP_MGR_PASSWORD_PROPERTY] = password
+
+
+  print '=' * 20
+  print 'Review Settings'
+  print '=' * 20
+  for property in ldap_property_list_reqd:
+    if property in ldap_property_value_map:
+      print("%s: %s" % (property, ldap_property_value_map[property]))
+
+  for property in ldap_property_list_opt:
+    if property != LDAP_MGR_PASSWORD_PROPERTY:
+      print("%s: %s" % (property, ldap_property_value_map[property]))
+    else:
+      print("%s: %s" % (property, "****"))
+
+  save_settings = get_YN_input("Save settings [y/n] (y)? ", True)
+
+  if save_settings:
+    if isSecure:
+      retCode = save_passwd_for_alias(LDAP_MGR_PASSWORD_ALIAS, password, masterKey)
+      if retCode != 0:
+        print 'Saving secure ldap password failed.'
+        return retCode
+    ldap_property_value_map[CLIENT_SECURITY_KEY] = 'ldap'
+    # Persisting values
+    update_properties(ldap_property_value_map)
+    print 'Saving...done'
+
+  print "Ambari Server 'LDAP setup' completed successfully. Exiting."
   return 0
 
+
 def reset_master_key():
   setup_master_key(resetKey=True)
 
@@ -2508,7 +2560,7 @@ def save_master_key(master_key, key_loca
     print_error_msg("Master key cannot be None.")
 
 
-def configure_ldap_password(isSecure=False, masterKey=None):
+def configure_ldap_password():
   passwordDefault = ""
   passwordPrompt = 'Enter LDAP Password: '
   passwordPattern = ".*"
@@ -2517,13 +2569,6 @@ def configure_ldap_password(isSecure=Fal
   password = read_password(passwordDefault, passwordPattern, passwordPrompt,
     passwordDescr)
 
-  if isSecure:
-    retCode = save_passwd_for_alias(LDAP_MGR_PASSWORD_ALIAS, password, masterKey)
-    if retCode != 0:
-      print 'Saving secure ldap password failed.'
-      return password
-    return get_alias_string(LDAP_MGR_PASSWORD_ALIAS)
-
   return password
 
 # Copy file to /tmp and save with file.# (largest # is latest file)

Modified: incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py?rev=1495634&r1=1495633&r2=1495634&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py (original)
+++ incubator/ambari/trunk/ambari-server/src/test/python/TestAmbaryServer.py Fri Jun 21 23:18:58 2013
@@ -2872,6 +2872,8 @@ class TestAmbariServer(TestCase):
     sys.stdout = sys.__stdout__
 
 
+  @patch.object(ambari_server, 'save_passwd_for_alias')
+  @patch.object(ambari_server, 'get_YN_input')
   @patch.object(ambari_server, 'update_properties')
   @patch.object(ambari_server, 'configure_ldap_password')
   @patch.object(ambari_server, 'get_validated_string_input')
@@ -2881,19 +2883,32 @@ class TestAmbariServer(TestCase):
   def test_setup_ldap(self, get_ambari_properties_method,
                 search_file_message, setup_master_key_method,
                 get_validated_string_input_method,
-                configure_ldap_password_method, update_properties_method):
+                configure_ldap_password_method, update_properties_method,
+                get_YN_input_method, save_passwd_for_alias_method):
     out = StringIO.StringIO()
     sys.stdout = out
     search_file_message.return_value = "filepath"
 
     configs = { ambari_server.SECURITY_MASTER_KEY_LOCATION : "filepath",
                 ambari_server.SECURITY_KEYS_DIR : tempfile.gettempdir(),
-                ambari_server.SECURITY_KEY_IS_PERSISTED : "true" }
+                ambari_server.SECURITY_KEY_IS_PERSISTED : "true"
+              }
 
     get_ambari_properties_method.return_value = configs
-    get_validated_string_input_method.return_value = "test"
-    configure_ldap_password_method.return_value = "${alias=fake}"
+    configure_ldap_password_method.return_value = "password"
     setup_master_key_method.return_value = (None, True, True)
+    get_YN_input_method.return_value = True
+    save_passwd_for_alias_method.return_value = 0
+
+    def side_effect(*args, **kwargs):
+      if 'Bind anonymously' in args[0]:
+        return 'true'
+      if args[1] == "true" or args[1] == "false":
+        return args[1]
+      else:
+        return "test"
+
+    get_validated_string_input_method.side_effect = side_effect
 
     ambari_server.setup_ldap()
 
@@ -2901,49 +2916,36 @@ class TestAmbariServer(TestCase):
     {
       "authentication.ldap.primaryUrl" : "test",
       "authentication.ldap.secondaryUrl" : "test",
-      "authentication.ldap.baseDn" : "test",
-      "authentication.ldap.bindAnonymously" : "test",
+      "authentication.ldap.useSSL" : "true",
       "authentication.ldap.usernameAttribute" : "test",
-      "authorization.ldap.groupBase" : "test",
-      "authorization.ldap.groupObjectClass" : "test",
-      "authorization.ldap.groupNamingAttr" : "test",
-      "authorization.ldap.groupMembershipAttr" : "test",
-      "authorization.ldap.adminGroupMappingRules" : "test",
-      "authorization.ldap.groupSearchFilter" : "test",
+      "authentication.ldap.baseDn" : "test",
       "authorization.userRoleName" : "test",
       "authorization.adminRoleName" : "test",
+      "authentication.ldap.bindAnonymously" : "true",
       "authentication.ldap.managerDn" : "test",
       "authentication.ldap.managerPassword" : \
-        configure_ldap_password_method.return_value
+        '${alias=ambari.ldap.manager.password}'
     }
 
-    self.assertEquals(update_properties_method.call_args[0][0],
-      ldap_properties_map)
+    self.assertEquals(sorted(update_properties_method.call_args[0][0]),
+      sorted(ldap_properties_map))
     self.assertTrue(update_properties_method.called)
     self.assertTrue(configure_ldap_password_method.called)
     self.assertTrue(get_validated_string_input_method.called)
+    self.assertTrue(get_YN_input_method.called)
 
     sys.stdout = sys.__stdout__
 
 
-  @patch.object(ambari_server, 'get_alias_string')
-  @patch.object(ambari_server, 'save_passwd_for_alias')
   @patch.object(ambari_server, 'read_password')
-  def test_configure_ldap_password(self, read_password_method,
-           save_passwd_for_alias_method, get_alias_string_method):
+  def test_configure_ldap_password(self, read_password_method):
     out = StringIO.StringIO()
     sys.stdout = out
     read_password_method.return_value = "blah"
-    save_passwd_for_alias_method.return_value = 0
-    get_alias_string_method.return_value = "${alias=somefake}"
 
-    ambari_server.configure_ldap_password(True, "aaa")
+    ambari_server.configure_ldap_password()
 
-    self.assertTrue(save_passwd_for_alias_method.called)
     self.assertTrue(read_password_method.called)
-    self.assertTrue(get_alias_string_method.called)
-    save_passwd_for_alias_method.assert_called_once_with(
-      ambari_server.LDAP_MGR_PASSWORD_ALIAS, "blah", "aaa")
 
     sys.stdout = sys.__stdout__