深入理解Spark 2.1 Core (十四):securityManager 类源码分析

本文深入解析了Spark中SecurityManager类的功能及其实现细节,包括权限设置、秘钥生成、SSL配置等方面的内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

securityManager主要用于权限设置,比如在使用yarn作为资源调度框架时,用于生成secret key进行登录。该类默认只用一个实例,所以的app使用同一个实例,下面是该类的所有源代码:

  1. private[spark] class SecurityManager(sparkConf: SparkConf)  
  2.   extends Logging with SecretKeyHolder {  
  3.   
  4.   // key used to store the spark secret in the Hadoop UGI  
  5.   private val sparkSecretLookupKey = "sparkCookie"  
  6.   
  7.   private val authOn = sparkConf.getBoolean("spark.authenticate"false)  
  8.   // keep spark.ui.acls.enable for backwards compatibility with 1.0  
  9.   private var aclsOn =  
  10.     sparkConf.getBoolean("spark.acls.enable", sparkConf.getBoolean("spark.ui.acls.enable"false))  
  11.   
  12.   // admin acls should be set before view or modify acls  
  13.   private var adminAcls: Set[String] =  
  14.     stringToSet(sparkConf.get("spark.admin.acls"""))  
  15.   
  16.   private var viewAcls: Set[String] = _  
  17.   
  18.   // list of users who have permission to modify the application. This should  
  19.   // apply to both UI and CLI for things like killing the application.  
  20.   private var modifyAcls: Set[String] = _  
  21.   
  22.   // always add the current user and SPARK_USER to the viewAcls  
  23.   private val defaultAclUsers = Set[String](System.getProperty("user.name"""),  
  24.     Utils.getCurrentUserName())  
  25.   
  26.   setViewAcls(defaultAclUsers, sparkConf.get("spark.ui.view.acls"""))  
  27.   setModifyAcls(defaultAclUsers, sparkConf.get("spark.modify.acls"""))  
  28.   
  29.   private val secretKey = generateSecretKey()  
  30.   logInfo("SecurityManager: authentication " + (if (authOn) "enabled" else "disabled") +  
  31.     "; ui acls " + (if (aclsOn) "enabled" else "disabled") +  
  32.     "; users with view permissions: " + viewAcls.toString() +  
  33.     "; users with modify permissions: " + modifyAcls.toString())  
  34.   
  35.   // Set our own authenticator to properly negotiate user/password for HTTP connections.  
  36.   // This is needed by the HTTP client fetching from the HttpServer. Put here so its  
  37.   // only set once.  
  38.   if (authOn) {  
  39.     Authenticator.setDefault(  
  40.       new Authenticator() {  
  41.         override def getPasswordAuthentication(): PasswordAuthentication = {  
  42.           var passAuth: PasswordAuthentication = null  
  43.           val userInfo = getRequestingURL().getUserInfo()  
  44.           if (userInfo != null) {  
  45.             val  parts = userInfo.split(":"2)  
  46.             passAuth = new PasswordAuthentication(parts(0), parts(1).toCharArray())  
  47.           }  
  48.           return passAuth  
  49.         }  
  50.       }  
  51.     )  
  52.   }  
  53.   
  54.   // the default SSL configuration - it will be used by all communication layers unless overwritten  
  55.   private val defaultSSLOptions = SSLOptions.parse(sparkConf, "spark.ssl", defaults = None)  
  56.   
  57.   // SSL configuration for different communication layers - they can override the default  
  58.   // configuration at a specified namespace. The namespace *must* start with spark.ssl.  
  59.   val fileServerSSLOptions = SSLOptions.parse(sparkConf, "spark.ssl.fs", Some(defaultSSLOptions))  
  60.   val akkaSSLOptions = SSLOptions.parse(sparkConf, "spark.ssl.akka", Some(defaultSSLOptions))  
  61.   
  62.   logDebug(s"SSLConfiguration for file server: $fileServerSSLOptions")  
  63.   logDebug(s"SSLConfiguration for Akka: $akkaSSLOptions")  
  64.   
  65.   val (sslSocketFactory, hostnameVerifier) = if (fileServerSSLOptions.enabled) {  
  66.     val trustStoreManagers =  
  67.       for (trustStore <- fileServerSSLOptions.trustStore) yield {  
  68.         val input = Files.asByteSource(fileServerSSLOptions.trustStore.get).openStream()  
  69.   
  70.         try {  
  71.           val ks = KeyStore.getInstance(KeyStore.getDefaultType)  
  72.           ks.load(input, fileServerSSLOptions.trustStorePassword.get.toCharArray)  
  73.   
  74.           val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)  
  75.           tmf.init(ks)  
  76.           tmf.getTrustManagers  
  77.         } finally {  
  78.           input.close()  
  79.         }  
  80.       }  
  81.   
  82.     lazy val credulousTrustStoreManagers = Array({  
  83.       logWarning("Using 'accept-all' trust manager for SSL connections.")  
  84.       new X509TrustManager {  
  85.         override def getAcceptedIssuers: Array[X509Certificate] = null  
  86.   
  87.         override def checkClientTrusted(x509Certificates: Array[X509Certificate], s: String) {}  
  88.   
  89.         override def checkServerTrusted(x509Certificates: Array[X509Certificate], s: String) {}  
  90.       }: TrustManager  
  91.     })  
  92.   
  93.     val sslContext = SSLContext.getInstance(fileServerSSLOptions.protocol.getOrElse("Default"))  
  94.     sslContext.init(null, trustStoreManagers.getOrElse(credulousTrustStoreManagers), null)  
  95.   
  96.     val hostVerifier = new HostnameVerifier {  
  97.       override def verify(s: String, sslSession: SSLSession): Boolean = true  
  98.     }  
  99.   
  100.     (Some(sslContext.getSocketFactory), Some(hostVerifier))  
  101.   } else {  
  102.     (None, None)  
  103.   }  
  104.   
  105.   /** 
  106.    * Split a comma separated String, filter out any empty items, and return a Set of strings 
  107.    */  
  108.   private def stringToSet(list: String): Set[String] = {  
  109.     list.split(',').map(_.trim).filter(!_.isEmpty).toSet  
  110.   }  
  111.   
  112.   /** 
  113.    * Admin acls should be set before the view or modify acls.  If you modify the admin 
  114.    * acls you should also set the view and modify acls again to pick up the changes. 
  115.    */  
  116.   def setViewAcls(defaultUsers: Set[String], allowedUsers: String) {  
  117.     viewAcls = (adminAcls ++ defaultUsers ++ stringToSet(allowedUsers))  
  118.     logInfo("Changing view acls to: " + viewAcls.mkString(","))  
  119.   }  
  120.   
  121.   def setViewAcls(defaultUser: String, allowedUsers: String) {  
  122.     setViewAcls(Set[String](defaultUser), allowedUsers)  
  123.   }  
  124.   
  125.   def getViewAcls: String = viewAcls.mkString(",")  
  126.   
  127.   /** 
  128.    * Admin acls should be set before the view or modify acls.  If you modify the admin 
  129.    * acls you should also set the view and modify acls again to pick up the changes. 
  130.    */  
  131.   def setModifyAcls(defaultUsers: Set[String], allowedUsers: String) {  
  132.     modifyAcls = (adminAcls ++ defaultUsers ++ stringToSet(allowedUsers))  
  133.     logInfo("Changing modify acls to: " + modifyAcls.mkString(","))  
  134.   }  
  135.   
  136.   def getModifyAcls: String = modifyAcls.mkString(",")  
  137.   
  138.   /** 
  139.    * Admin acls should be set before the view or modify acls.  If you modify the admin 
  140.    * acls you should also set the view and modify acls again to pick up the changes. 
  141.    */  
  142.   def setAdminAcls(adminUsers: String) {  
  143.     adminAcls = stringToSet(adminUsers)  
  144.     logInfo("Changing admin acls to: " + adminAcls.mkString(","))  
  145.   }  
  146.   
  147.   def setAcls(aclSetting: Boolean) {  
  148.     aclsOn = aclSetting  
  149.     logInfo("Changing acls enabled to: " + aclsOn)  
  150.   }  
  151.   
  152.   /** 
  153.    * Generates or looks up the secret key. 
  154.    * 
  155.    * The way the key is stored depends on the Spark deployment mode. Yarn 
  156.    * uses the Hadoop UGI. 
  157.    * 
  158.    * For non-Yarn deployments, If the config variable is not set 
  159.    * we throw an exception. 
  160.    */  
  161.   private def generateSecretKey(): String = {  
  162.     if (!isAuthenticationEnabled) return null  
  163.     // first check to see if the secret is already set, else generate a new one if on yarn  
  164.     val sCookie = if (SparkHadoopUtil.get.isYarnMode) {  
  165.       val secretKey = SparkHadoopUtil.get.getSecretKeyFromUserCredentials(sparkSecretLookupKey)  
  166.       if (secretKey != null) {  
  167.         logDebug("in yarn mode, getting secret from credentials")  
  168.         return new Text(secretKey).toString  
  169.       } else {  
  170.         logDebug("getSecretKey: yarn mode, secret key from credentials is null")  
  171.       }  
  172.       val cookie = akka.util.Crypt.generateSecureCookie  
  173.       // if we generated the secret then we must be the first so lets set it so t  
  174.       // gets used by everyone else  
  175.       SparkHadoopUtil.get.addSecretKeyToUserCredentials(sparkSecretLookupKey, cookie)  
  176.       logInfo("adding secret to credentials in yarn mode")  
  177.       cookie  
  178.     } else {  
  179.       // user must have set spark.authenticate.secret config  
  180.       sparkConf.getOption("spark.authenticate.secret") match {  
  181.         case Some(value) => value  
  182.         case None => throw new Exception("Error: a secret key must be specified via the " +  
  183.           "spark.authenticate.secret config")  
  184.       }  
  185.     }  
  186.     sCookie  
  187.   }  
  188.   
  189.   /** 
  190.    * Check to see if Acls for the UI are enabled 
  191.    * @return true if UI authentication is enabled, otherwise false 
  192.    */  
  193.   def aclsEnabled(): Boolean = aclsOn  
  194.   
  195.   /** 
  196.    * Checks the given user against the view acl list to see if they have 
  197.    * authorization to view the UI. If the UI acls are disabled 
  198.    * via spark.acls.enable, all users have view access. If the user is null 
  199.    * it is assumed authentication is off and all users have access. 
  200.    * 
  201.    * @param user to see if is authorized 
  202.    * @return true is the user has permission, otherwise false 
  203.    */  
  204.   def checkUIViewPermissions(user: String): Boolean = {  
  205.     logDebug("user=" + user + " aclsEnabled=" + aclsEnabled() + " viewAcls=" +  
  206.       viewAcls.mkString(","))  
  207.     !aclsEnabled || user == null || viewAcls.contains(user)  
  208.   }  
  209.   
  210.   /** 
  211.    * Checks the given user against the modify acl list to see if they have 
  212.    * authorization to modify the application. If the UI acls are disabled 
  213.    * via spark.acls.enable, all users have modify access. If the user is null 
  214.    * it is assumed authentication isn't turned on and all users have access. 
  215.    * 
  216.    * @param user to see if is authorized 
  217.    * @return true is the user has permission, otherwise false 
  218.    */  
  219.   def checkModifyPermissions(user: String): Boolean = {  
  220.     logDebug("user=" + user + " aclsEnabled=" + aclsEnabled() + " modifyAcls=" +  
  221.       modifyAcls.mkString(","))  
  222.     !aclsEnabled || user == null || modifyAcls.contains(user)  
  223.   }  
  224.   
  225.   
  226.   /** 
  227.    * Check to see if authentication for the Spark communication protocols is enabled 
  228.    * @return true if authentication is enabled, otherwise false 
  229.    */  
  230.   def isAuthenticationEnabled(): Boolean = authOn  
  231.   
  232.   /** 
  233.    * Gets the user used for authenticating HTTP connections. 
  234.    * For now use a single hardcoded user. 
  235.    * @return the HTTP user as a String 
  236.    */  
  237.   def getHttpUser(): String = "sparkHttpUser"  
  238.   
  239.   /** 
  240.    * Gets the user used for authenticating SASL connections. 
  241.    * For now use a single hardcoded user. 
  242.    * @return the SASL user as a String 
  243.    */  
  244.   def getSaslUser(): String = "sparkSaslUser"  
  245.   
  246.   /** 
  247.    * Gets the secret key. 
  248.    * @return the secret key as a String if authentication is enabled, otherwise returns null 
  249.    */  
  250.   def getSecretKey(): String = secretKey  
  251.   
  252.   // Default SecurityManager only has a single secret key, so ignore appId.  
  253.   override def getSaslUser(appId: String): String = getSaslUser()  
  254.   override def getSecretKey(appId: String): String = getSecretKey()  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值