1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *    http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.spark
19
20import java.io.File
21
22import org.apache.spark.security.GroupMappingServiceProvider
23import org.apache.spark.util.{ResetSystemProperties, SparkConfWithEnv, Utils}
24
25class DummyGroupMappingServiceProvider extends GroupMappingServiceProvider {
26
27  val userGroups: Set[String] = Set[String]("group1", "group2", "group3")
28
29  override def getGroups(username: String): Set[String] = {
30    userGroups
31  }
32}
33
34class SecurityManagerSuite extends SparkFunSuite with ResetSystemProperties {
35
36  test("set security with conf") {
37    val conf = new SparkConf
38    conf.set("spark.authenticate", "true")
39    conf.set("spark.authenticate.secret", "good")
40    conf.set("spark.ui.acls.enable", "true")
41    conf.set("spark.ui.view.acls", "user1,user2")
42    val securityManager = new SecurityManager(conf);
43    assert(securityManager.isAuthenticationEnabled() === true)
44    assert(securityManager.aclsEnabled() === true)
45    assert(securityManager.checkUIViewPermissions("user1") === true)
46    assert(securityManager.checkUIViewPermissions("user2") === true)
47    assert(securityManager.checkUIViewPermissions("user3") === false)
48  }
49
50  test("set security with conf for groups") {
51    val conf = new SparkConf
52    conf.set("spark.authenticate", "true")
53    conf.set("spark.authenticate.secret", "good")
54    conf.set("spark.ui.acls.enable", "true")
55    conf.set("spark.ui.view.acls.groups", "group1,group2")
56    // default ShellBasedGroupsMappingProvider is used to resolve user groups
57    val securityManager = new SecurityManager(conf);
58    // assuming executing user does not belong to group1,group2
59    assert(securityManager.checkUIViewPermissions("user1") === false)
60    assert(securityManager.checkUIViewPermissions("user2") === false)
61
62    val conf2 = new SparkConf
63    conf2.set("spark.authenticate", "true")
64    conf2.set("spark.authenticate.secret", "good")
65    conf2.set("spark.ui.acls.enable", "true")
66    conf2.set("spark.ui.view.acls.groups", "group1,group2")
67    // explicitly specify a custom GroupsMappingServiceProvider
68    conf2.set("spark.user.groups.mapping", "org.apache.spark.DummyGroupMappingServiceProvider")
69
70    val securityManager2 = new SecurityManager(conf2);
71    // group4,group5 do not match
72    assert(securityManager2.checkUIViewPermissions("user1") === true)
73    assert(securityManager2.checkUIViewPermissions("user2") === true)
74
75    val conf3 = new SparkConf
76    conf3.set("spark.authenticate", "true")
77    conf3.set("spark.authenticate.secret", "good")
78    conf3.set("spark.ui.acls.enable", "true")
79    conf3.set("spark.ui.view.acls.groups", "group4,group5")
80    // explicitly specify a bogus GroupsMappingServiceProvider
81    conf3.set("spark.user.groups.mapping", "BogusServiceProvider")
82
83    val securityManager3 = new SecurityManager(conf3);
84    // BogusServiceProvider cannot be loaded and an error is logged returning an empty group set
85    assert(securityManager3.checkUIViewPermissions("user1") === false)
86    assert(securityManager3.checkUIViewPermissions("user2") === false)
87  }
88
89  test("set security with api") {
90    val conf = new SparkConf
91    conf.set("spark.ui.view.acls", "user1,user2")
92    val securityManager = new SecurityManager(conf);
93    securityManager.setAcls(true)
94    assert(securityManager.aclsEnabled() === true)
95    securityManager.setAcls(false)
96    assert(securityManager.aclsEnabled() === false)
97
98    // acls are off so doesn't matter what view acls set to
99    assert(securityManager.checkUIViewPermissions("user4") === true)
100
101    securityManager.setAcls(true)
102    assert(securityManager.aclsEnabled() === true)
103    securityManager.setViewAcls(Set[String]("user5"), "user6,user7")
104    assert(securityManager.checkUIViewPermissions("user1") === false)
105    assert(securityManager.checkUIViewPermissions("user5") === true)
106    assert(securityManager.checkUIViewPermissions("user6") === true)
107    assert(securityManager.checkUIViewPermissions("user7") === true)
108    assert(securityManager.checkUIViewPermissions("user8") === false)
109    assert(securityManager.checkUIViewPermissions(null) === true)
110  }
111
112  test("set security with api for groups") {
113    val conf = new SparkConf
114    conf.set("spark.user.groups.mapping", "org.apache.spark.DummyGroupMappingServiceProvider")
115
116    val securityManager = new SecurityManager(conf);
117    securityManager.setAcls(true)
118    securityManager.setViewAclsGroups("group1,group2")
119
120    // group1,group2 match
121    assert(securityManager.checkUIViewPermissions("user1") === true)
122    assert(securityManager.checkUIViewPermissions("user2") === true)
123
124    // change groups so they do not match
125    securityManager.setViewAclsGroups("group4,group5")
126    assert(securityManager.checkUIViewPermissions("user1") === false)
127    assert(securityManager.checkUIViewPermissions("user2") === false)
128
129    val conf2 = new SparkConf
130    conf.set("spark.user.groups.mapping", "BogusServiceProvider")
131
132    val securityManager2 = new SecurityManager(conf2)
133    securityManager2.setAcls(true)
134    securityManager2.setViewAclsGroups("group1,group2")
135
136    // group1,group2 do not match because of BogusServiceProvider
137    assert(securityManager.checkUIViewPermissions("user1") === false)
138    assert(securityManager.checkUIViewPermissions("user2") === false)
139
140    // setting viewAclsGroups to empty should still not match because of BogusServiceProvider
141    securityManager2.setViewAclsGroups("")
142    assert(securityManager.checkUIViewPermissions("user1") === false)
143    assert(securityManager.checkUIViewPermissions("user2") === false)
144  }
145
146  test("set security modify acls") {
147    val conf = new SparkConf
148    conf.set("spark.modify.acls", "user1,user2")
149
150    val securityManager = new SecurityManager(conf);
151    securityManager.setAcls(true)
152    assert(securityManager.aclsEnabled() === true)
153    securityManager.setAcls(false)
154    assert(securityManager.aclsEnabled() === false)
155
156    // acls are off so doesn't matter what view acls set to
157    assert(securityManager.checkModifyPermissions("user4") === true)
158
159    securityManager.setAcls(true)
160    assert(securityManager.aclsEnabled() === true)
161    securityManager.setModifyAcls(Set("user5"), "user6,user7")
162    assert(securityManager.checkModifyPermissions("user1") === false)
163    assert(securityManager.checkModifyPermissions("user5") === true)
164    assert(securityManager.checkModifyPermissions("user6") === true)
165    assert(securityManager.checkModifyPermissions("user7") === true)
166    assert(securityManager.checkModifyPermissions("user8") === false)
167    assert(securityManager.checkModifyPermissions(null) === true)
168  }
169
170  test("set security modify acls for groups") {
171    val conf = new SparkConf
172    conf.set("spark.user.groups.mapping", "org.apache.spark.DummyGroupMappingServiceProvider")
173
174    val securityManager = new SecurityManager(conf);
175    securityManager.setAcls(true)
176    securityManager.setModifyAclsGroups("group1,group2")
177
178    // group1,group2 match
179    assert(securityManager.checkModifyPermissions("user1") === true)
180    assert(securityManager.checkModifyPermissions("user2") === true)
181
182    // change groups so they do not match
183    securityManager.setModifyAclsGroups("group4,group5")
184    assert(securityManager.checkModifyPermissions("user1") === false)
185    assert(securityManager.checkModifyPermissions("user2") === false)
186
187    // change so they match again
188    securityManager.setModifyAclsGroups("group2,group3")
189    assert(securityManager.checkModifyPermissions("user1") === true)
190    assert(securityManager.checkModifyPermissions("user2") === true)
191  }
192
193  test("set security admin acls") {
194    val conf = new SparkConf
195    conf.set("spark.admin.acls", "user1,user2")
196    conf.set("spark.ui.view.acls", "user3")
197    conf.set("spark.modify.acls", "user4")
198
199    val securityManager = new SecurityManager(conf);
200    securityManager.setAcls(true)
201    assert(securityManager.aclsEnabled() === true)
202
203    assert(securityManager.checkModifyPermissions("user1") === true)
204    assert(securityManager.checkModifyPermissions("user2") === true)
205    assert(securityManager.checkModifyPermissions("user4") === true)
206    assert(securityManager.checkModifyPermissions("user3") === false)
207    assert(securityManager.checkModifyPermissions("user5") === false)
208    assert(securityManager.checkModifyPermissions(null) === true)
209    assert(securityManager.checkUIViewPermissions("user1") === true)
210    assert(securityManager.checkUIViewPermissions("user2") === true)
211    assert(securityManager.checkUIViewPermissions("user3") === true)
212    assert(securityManager.checkUIViewPermissions("user4") === false)
213    assert(securityManager.checkUIViewPermissions("user5") === false)
214    assert(securityManager.checkUIViewPermissions(null) === true)
215
216    securityManager.setAdminAcls("user6")
217    securityManager.setViewAcls(Set[String]("user8"), "user9")
218    securityManager.setModifyAcls(Set("user11"), "user9")
219    assert(securityManager.checkModifyPermissions("user6") === true)
220    assert(securityManager.checkModifyPermissions("user11") === true)
221    assert(securityManager.checkModifyPermissions("user9") === true)
222    assert(securityManager.checkModifyPermissions("user1") === false)
223    assert(securityManager.checkModifyPermissions("user4") === false)
224    assert(securityManager.checkModifyPermissions(null) === true)
225    assert(securityManager.checkUIViewPermissions("user6") === true)
226    assert(securityManager.checkUIViewPermissions("user8") === true)
227    assert(securityManager.checkUIViewPermissions("user9") === true)
228    assert(securityManager.checkUIViewPermissions("user1") === false)
229    assert(securityManager.checkUIViewPermissions("user3") === false)
230    assert(securityManager.checkUIViewPermissions(null) === true)
231  }
232
233  test("set security admin acls for groups") {
234    val conf = new SparkConf
235    conf.set("spark.admin.acls.groups", "group1")
236    conf.set("spark.ui.view.acls.groups", "group2")
237    conf.set("spark.modify.acls.groups", "group3")
238    conf.set("spark.user.groups.mapping", "org.apache.spark.DummyGroupMappingServiceProvider")
239
240    val securityManager = new SecurityManager(conf);
241    securityManager.setAcls(true)
242    assert(securityManager.aclsEnabled() === true)
243
244    // group1,group2,group3 match
245    assert(securityManager.checkModifyPermissions("user1") === true)
246    assert(securityManager.checkUIViewPermissions("user1") === true)
247
248    // change admin groups so they do not match. view and modify groups are set to admin groups
249    securityManager.setAdminAclsGroups("group4,group5")
250    // invoke the set ui and modify to propagate the changes
251    securityManager.setViewAclsGroups("")
252    securityManager.setModifyAclsGroups("")
253
254    assert(securityManager.checkModifyPermissions("user1") === false)
255    assert(securityManager.checkUIViewPermissions("user1") === false)
256
257    // change modify groups so they match
258    securityManager.setModifyAclsGroups("group3")
259    assert(securityManager.checkModifyPermissions("user1") === true)
260    assert(securityManager.checkUIViewPermissions("user1") === false)
261
262    // change view groups so they match
263    securityManager.setViewAclsGroups("group2")
264    securityManager.setModifyAclsGroups("group4")
265    assert(securityManager.checkModifyPermissions("user1") === false)
266    assert(securityManager.checkUIViewPermissions("user1") === true)
267
268    // change modify and view groups so they do not match
269    securityManager.setViewAclsGroups("group7")
270    securityManager.setModifyAclsGroups("group8")
271    assert(securityManager.checkModifyPermissions("user1") === false)
272    assert(securityManager.checkUIViewPermissions("user1") === false)
273  }
274
275  test("set security with * in acls") {
276    val conf = new SparkConf
277    conf.set("spark.ui.acls.enable", "true")
278    conf.set("spark.admin.acls", "user1,user2")
279    conf.set("spark.ui.view.acls", "*")
280    conf.set("spark.modify.acls", "user4")
281
282    val securityManager = new SecurityManager(conf)
283    assert(securityManager.aclsEnabled() === true)
284
285    // check for viewAcls with *
286    assert(securityManager.checkUIViewPermissions("user1") === true)
287    assert(securityManager.checkUIViewPermissions("user5") === true)
288    assert(securityManager.checkUIViewPermissions("user6") === true)
289    assert(securityManager.checkModifyPermissions("user4") === true)
290    assert(securityManager.checkModifyPermissions("user7") === false)
291    assert(securityManager.checkModifyPermissions("user8") === false)
292
293    // check for modifyAcls with *
294    securityManager.setModifyAcls(Set("user4"), "*")
295    assert(securityManager.checkModifyPermissions("user7") === true)
296    assert(securityManager.checkModifyPermissions("user8") === true)
297
298    securityManager.setAdminAcls("user1,user2")
299    securityManager.setModifyAcls(Set("user1"), "user2")
300    securityManager.setViewAcls(Set("user1"), "user2")
301    assert(securityManager.checkUIViewPermissions("user5") === false)
302    assert(securityManager.checkUIViewPermissions("user6") === false)
303    assert(securityManager.checkModifyPermissions("user7") === false)
304    assert(securityManager.checkModifyPermissions("user8") === false)
305
306    // check for adminAcls with *
307    securityManager.setAdminAcls("user1,*")
308    securityManager.setModifyAcls(Set("user1"), "user2")
309    securityManager.setViewAcls(Set("user1"), "user2")
310    assert(securityManager.checkUIViewPermissions("user5") === true)
311    assert(securityManager.checkUIViewPermissions("user6") === true)
312    assert(securityManager.checkModifyPermissions("user7") === true)
313    assert(securityManager.checkModifyPermissions("user8") === true)
314  }
315
316  test("set security with * in acls for groups") {
317    val conf = new SparkConf
318    conf.set("spark.ui.acls.enable", "true")
319    conf.set("spark.admin.acls.groups", "group4,group5")
320    conf.set("spark.ui.view.acls.groups", "*")
321    conf.set("spark.modify.acls.groups", "group6")
322
323    val securityManager = new SecurityManager(conf)
324    assert(securityManager.aclsEnabled() === true)
325
326    // check for viewAclsGroups with *
327    assert(securityManager.checkUIViewPermissions("user1") === true)
328    assert(securityManager.checkUIViewPermissions("user2") === true)
329    assert(securityManager.checkModifyPermissions("user1") === false)
330    assert(securityManager.checkModifyPermissions("user2") === false)
331
332    // check for modifyAcls with *
333    securityManager.setModifyAclsGroups("*")
334    securityManager.setViewAclsGroups("group6")
335    assert(securityManager.checkUIViewPermissions("user1") === false)
336    assert(securityManager.checkUIViewPermissions("user2") === false)
337    assert(securityManager.checkModifyPermissions("user1") === true)
338    assert(securityManager.checkModifyPermissions("user2") === true)
339
340    // check for adminAcls with *
341    securityManager.setAdminAclsGroups("group9,*")
342    securityManager.setModifyAclsGroups("group4,group5")
343    securityManager.setViewAclsGroups("group6,group7")
344    assert(securityManager.checkUIViewPermissions("user5") === true)
345    assert(securityManager.checkUIViewPermissions("user6") === true)
346    assert(securityManager.checkModifyPermissions("user7") === true)
347    assert(securityManager.checkModifyPermissions("user8") === true)
348  }
349
350  test("security for groups default behavior") {
351    // no groups or userToGroupsMapper provided
352    // this will default to the ShellBasedGroupsMappingProvider
353    val conf = new SparkConf
354
355    val securityManager = new SecurityManager(conf)
356    securityManager.setAcls(true)
357
358    assert(securityManager.checkUIViewPermissions("user1") === false)
359    assert(securityManager.checkModifyPermissions("user1") === false)
360
361    // set groups only
362    securityManager.setAdminAclsGroups("group1,group2")
363    assert(securityManager.checkUIViewPermissions("user1") === false)
364    assert(securityManager.checkModifyPermissions("user1") === false)
365  }
366
367  test("ssl on setup") {
368    val conf = SSLSampleConfigs.sparkSSLConfig()
369    val expectedAlgorithms = Set(
370    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
371    "TLS_RSA_WITH_AES_256_CBC_SHA256",
372    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
373    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
374    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
375    "SSL_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
376    "SSL_RSA_WITH_AES_256_CBC_SHA256",
377    "SSL_DHE_RSA_WITH_AES_256_CBC_SHA256",
378    "SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
379    "SSL_DHE_RSA_WITH_AES_128_CBC_SHA256")
380
381    val securityManager = new SecurityManager(conf)
382
383    assert(securityManager.fileServerSSLOptions.enabled === true)
384
385    assert(securityManager.sslSocketFactory.isDefined === true)
386    assert(securityManager.hostnameVerifier.isDefined === true)
387
388    assert(securityManager.fileServerSSLOptions.trustStore.isDefined === true)
389    assert(securityManager.fileServerSSLOptions.trustStore.get.getName === "truststore")
390    assert(securityManager.fileServerSSLOptions.keyStore.isDefined === true)
391    assert(securityManager.fileServerSSLOptions.keyStore.get.getName === "keystore")
392    assert(securityManager.fileServerSSLOptions.trustStorePassword === Some("password"))
393    assert(securityManager.fileServerSSLOptions.keyStorePassword === Some("password"))
394    assert(securityManager.fileServerSSLOptions.keyPassword === Some("password"))
395    assert(securityManager.fileServerSSLOptions.protocol === Some("TLSv1.2"))
396    assert(securityManager.fileServerSSLOptions.enabledAlgorithms === expectedAlgorithms)
397  }
398
399  test("ssl off setup") {
400    val file = File.createTempFile("SSLOptionsSuite", "conf", Utils.createTempDir())
401
402    System.setProperty("spark.ssl.configFile", file.getAbsolutePath)
403    val conf = new SparkConf()
404
405    val securityManager = new SecurityManager(conf)
406
407    assert(securityManager.fileServerSSLOptions.enabled === false)
408    assert(securityManager.sslSocketFactory.isDefined === false)
409    assert(securityManager.hostnameVerifier.isDefined === false)
410  }
411
412  test("missing secret authentication key") {
413    val conf = new SparkConf().set("spark.authenticate", "true")
414    intercept[IllegalArgumentException] {
415      new SecurityManager(conf)
416    }
417  }
418
419  test("secret authentication key") {
420    val key = "very secret key"
421    val conf = new SparkConf()
422      .set(SecurityManager.SPARK_AUTH_CONF, "true")
423      .set(SecurityManager.SPARK_AUTH_SECRET_CONF, key)
424    assert(key === new SecurityManager(conf).getSecretKey())
425
426    val keyFromEnv = "very secret key from env"
427    val conf2 = new SparkConfWithEnv(Map(SecurityManager.ENV_AUTH_SECRET -> keyFromEnv))
428      .set(SecurityManager.SPARK_AUTH_CONF, "true")
429      .set(SecurityManager.SPARK_AUTH_SECRET_CONF, key)
430    assert(keyFromEnv === new SecurityManager(conf2).getSecretKey())
431  }
432
433}
434
435