@@ -41,10 +41,19 @@ import org.apache.spark.deploy.SparkHadoopUtil
41
41
* secure the UI if it has data that other users should not be allowed to see. The javax
42
42
* servlet filter specified by the user can authenticate the user and then once the user
43
43
* is logged in, Spark can compare that user versus the view acls to make sure they are
44
- * authorized to view the UI. The configs 'spark.ui. acls.enable' and 'spark.ui.view.acls'
44
+ * authorized to view the UI. The configs 'spark.acls.enable' and 'spark.ui.view.acls'
45
45
* control the behavior of the acls. Note that the person who started the application
46
46
* always has view access to the UI.
47
47
*
48
+ * Spark has a set of modify acls (`spark.modify.acls`) that controls which users have permission
49
+ * to modify a single application. This would include things like killing the application. By
50
+ * default the person who started the application has modify access. For modify access through
51
+ * the UI, you must have a filter that does authentication in place for the modify acls to work
52
+ * properly.
53
+ *
54
+ * Spark also has a set of admin acls (`spark.admin.acls`) which is a set of users/administrators
55
+ * who always have permission to view or modify the Spark application.
56
+ *
48
57
* Spark does not currently support encryption after authentication.
49
58
*
50
59
* At this point spark has multiple communication protocols that need to be secured and
@@ -137,18 +146,32 @@ private[spark] class SecurityManager(sparkConf: SparkConf) extends Logging {
137
146
private val sparkSecretLookupKey = " sparkCookie"
138
147
139
148
private val authOn = sparkConf.getBoolean(" spark.authenticate" , false )
140
- private var uiAclsOn = sparkConf.getBoolean(" spark.ui.acls.enable" , false )
149
+ // keep spark.ui.acls.enable for backwards compatibility with 1.0
150
+ private var aclsOn = sparkConf.getOption(" spark.acls.enable" ).getOrElse(
151
+ sparkConf.get(" spark.ui.acls.enable" , " false" )).toBoolean
152
+
153
+ // admin acls should be set before view or modify acls
154
+ private var adminAcls : Set [String ] =
155
+ stringToSet(sparkConf.get(" spark.admin.acls" , " " ))
141
156
142
157
private var viewAcls : Set [String ] = _
158
+
159
+ // list of users who have permission to modify the application. This should
160
+ // apply to both UI and CLI for things like killing the application.
161
+ private var modifyAcls : Set [String ] = _
162
+
143
163
// always add the current user and SPARK_USER to the viewAcls
144
- private val defaultAclUsers = Seq [String ](System .getProperty(" user.name" , " " ),
164
+ private val defaultAclUsers = Set [String ](System .getProperty(" user.name" , " " ),
145
165
Option (System .getenv(" SPARK_USER" )).getOrElse(" " ))
166
+
146
167
setViewAcls(defaultAclUsers, sparkConf.get(" spark.ui.view.acls" , " " ))
168
+ setModifyAcls(defaultAclUsers, sparkConf.get(" spark.modify.acls" , " " ))
147
169
148
170
private val secretKey = generateSecretKey()
149
171
logInfo(" SecurityManager: authentication " + (if (authOn) " enabled" else " disabled" ) +
150
- " ; ui acls " + (if (uiAclsOn) " enabled" else " disabled" ) +
151
- " ; users with view permissions: " + viewAcls.toString())
172
+ " ; ui acls " + (if (aclsOn) " enabled" else " disabled" ) +
173
+ " ; users with view permissions: " + viewAcls.toString() +
174
+ " ; users with modify permissions: " + modifyAcls.toString())
152
175
153
176
// Set our own authenticator to properly negotiate user/password for HTTP connections.
154
177
// This is needed by the HTTP client fetching from the HttpServer. Put here so its
@@ -169,18 +192,51 @@ private[spark] class SecurityManager(sparkConf: SparkConf) extends Logging {
169
192
)
170
193
}
171
194
172
- private [spark] def setViewAcls (defaultUsers : Seq [String ], allowedUsers : String ) {
173
- viewAcls = (defaultUsers ++ allowedUsers.split(',' )).map(_.trim()).filter(! _.isEmpty).toSet
195
+ /**
196
+ * Split a comma separated String, filter out any empty items, and return a Set of strings
197
+ */
198
+ private def stringToSet (list : String ): Set [String ] = {
199
+ list.split(',' ).map(_.trim).filter(! _.isEmpty).toSet
200
+ }
201
+
202
+ /**
203
+ * Admin acls should be set before the view or modify acls. If you modify the admin
204
+ * acls you should also set the view and modify acls again to pick up the changes.
205
+ */
206
+ def setViewAcls (defaultUsers : Set [String ], allowedUsers : String ) {
207
+ viewAcls = (adminAcls ++ defaultUsers ++ stringToSet(allowedUsers))
174
208
logInfo(" Changing view acls to: " + viewAcls.mkString(" ," ))
175
209
}
176
210
177
- private [spark] def setViewAcls (defaultUser : String , allowedUsers : String ) {
178
- setViewAcls(Seq [String ](defaultUser), allowedUsers)
211
+ def setViewAcls (defaultUser : String , allowedUsers : String ) {
212
+ setViewAcls(Set [String ](defaultUser), allowedUsers)
213
+ }
214
+
215
+ def getViewAcls : String = viewAcls.mkString(" ," )
216
+
217
+ /**
218
+ * Admin acls should be set before the view or modify acls. If you modify the admin
219
+ * acls you should also set the view and modify acls again to pick up the changes.
220
+ */
221
+ def setModifyAcls (defaultUsers : Set [String ], allowedUsers : String ) {
222
+ modifyAcls = (adminAcls ++ defaultUsers ++ stringToSet(allowedUsers))
223
+ logInfo(" Changing modify acls to: " + modifyAcls.mkString(" ," ))
224
+ }
225
+
226
+ def getModifyAcls : String = modifyAcls.mkString(" ," )
227
+
228
+ /**
229
+ * Admin acls should be set before the view or modify acls. If you modify the admin
230
+ * acls you should also set the view and modify acls again to pick up the changes.
231
+ */
232
+ def setAdminAcls (adminUsers : String ) {
233
+ adminAcls = stringToSet(adminUsers)
234
+ logInfo(" Changing admin acls to: " + adminAcls.mkString(" ," ))
179
235
}
180
236
181
- private [spark] def setUIAcls (aclSetting : Boolean ) {
182
- uiAclsOn = aclSetting
183
- logInfo(" Changing acls enabled to: " + uiAclsOn )
237
+ def setAcls (aclSetting : Boolean ) {
238
+ aclsOn = aclSetting
239
+ logInfo(" Changing acls enabled to: " + aclsOn )
184
240
}
185
241
186
242
/**
@@ -224,22 +280,39 @@ private[spark] class SecurityManager(sparkConf: SparkConf) extends Logging {
224
280
* Check to see if Acls for the UI are enabled
225
281
* @return true if UI authentication is enabled, otherwise false
226
282
*/
227
- def uiAclsEnabled (): Boolean = uiAclsOn
283
+ def aclsEnabled (): Boolean = aclsOn
228
284
229
285
/**
230
286
* Checks the given user against the view acl list to see if they have
231
- * authorization to view the UI. If the UI acls must are disabled
232
- * via spark.ui.acls.enable, all users have view access.
287
+ * authorization to view the UI. If the UI acls are disabled
288
+ * via spark.acls.enable, all users have view access. If the user is null
289
+ * it is assumed authentication is off and all users have access.
233
290
*
234
291
* @param user to see if is authorized
235
292
* @return true is the user has permission, otherwise false
236
293
*/
237
294
def checkUIViewPermissions (user : String ): Boolean = {
238
- logDebug(" user=" + user + " uiAclsEnabled =" + uiAclsEnabled () + " viewAcls=" +
295
+ logDebug(" user=" + user + " aclsEnabled =" + aclsEnabled () + " viewAcls=" +
239
296
viewAcls.mkString(" ," ))
240
- if (uiAclsEnabled () && (user != null ) && (! viewAcls.contains(user))) false else true
297
+ if (aclsEnabled () && (user != null ) && (! viewAcls.contains(user))) false else true
241
298
}
242
299
300
+ /**
301
+ * Checks the given user against the modify acl list to see if they have
302
+ * authorization to modify the application. If the UI acls are disabled
303
+ * via spark.acls.enable, all users have modify access. If the user is null
304
+ * it is assumed authentication isn't turned on and all users have access.
305
+ *
306
+ * @param user to see if is authorized
307
+ * @return true is the user has permission, otherwise false
308
+ */
309
+ def checkModifyPermissions (user : String ): Boolean = {
310
+ logDebug(" user=" + user + " aclsEnabled=" + aclsEnabled() + " modifyAcls=" +
311
+ modifyAcls.mkString(" ," ))
312
+ if (aclsEnabled() && (user != null ) && (! modifyAcls.contains(user))) false else true
313
+ }
314
+
315
+
243
316
/**
244
317
* Check to see if authentication for the Spark communication protocols is enabled
245
318
* @return true if authentication is enabled, otherwise false
0 commit comments