Skip to content

Commit f351763

Browse files
committed
Add Security to Spark - Akka, Http, ConnectionManager, UI to use servlets
1 parent fe8a354 commit f351763

File tree

62 files changed

+1746
-234
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1746
-234
lines changed

core/pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,18 @@
5252
<groupId>org.apache.zookeeper</groupId>
5353
<artifactId>zookeeper</artifactId>
5454
</dependency>
55+
<dependency>
56+
<groupId>org.eclipse.jetty</groupId>
57+
<artifactId>jetty-plus</artifactId>
58+
</dependency>
59+
<dependency>
60+
<groupId>org.eclipse.jetty</groupId>
61+
<artifactId>jetty-security</artifactId>
62+
</dependency>
63+
<dependency>
64+
<groupId>org.eclipse.jetty</groupId>
65+
<artifactId>jetty-util</artifactId>
66+
</dependency>
5567
<dependency>
5668
<groupId>org.eclipse.jetty</groupId>
5769
<artifactId>jetty-server</artifactId>
@@ -90,6 +102,10 @@
90102
<artifactId>chill-java</artifactId>
91103
<version>0.3.1</version>
92104
</dependency>
105+
<dependency>
106+
<groupId>commons-net</groupId>
107+
<artifactId>commons-net</artifactId>
108+
</dependency>
93109
<dependency>
94110
<groupId>${akka.group}</groupId>
95111
<artifactId>akka-remote_${scala.binary.version}</artifactId>
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.spark;
20+
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
import java.io.IOException;
25+
26+
import javax.security.auth.callback.Callback;
27+
import javax.security.auth.callback.CallbackHandler;
28+
import javax.security.auth.callback.NameCallback;
29+
import javax.security.auth.callback.PasswordCallback;
30+
import javax.security.auth.callback.UnsupportedCallbackException;
31+
import javax.security.sasl.RealmCallback;
32+
import javax.security.sasl.RealmChoiceCallback;
33+
import javax.security.sasl.Sasl;
34+
import javax.security.sasl.SaslException;
35+
import javax.security.sasl.SaslClient;
36+
37+
/**
38+
* Implements SASL Client logic for Spark
39+
* Some of the code borrowed from Giraph and Hadoop
40+
*/
41+
public class SparkSaslClient {
42+
/** Class logger */
43+
private static Logger LOG = LoggerFactory.getLogger(SparkSaslClient.class);
44+
45+
/**
46+
* Used to respond to server's counterpart, SaslServer with SASL tokens
47+
* represented as byte arrays.
48+
*/
49+
private SaslClient saslClient;
50+
51+
/**
52+
* Create a SaslClient for authentication with BSP servers.
53+
*/
54+
public SparkSaslClient(SecurityManager securityMgr) {
55+
try {
56+
saslClient = Sasl.createSaslClient(new String[] { SparkSaslServer.DIGEST },
57+
null, null, SparkSaslServer.SASL_DEFAULT_REALM,
58+
SparkSaslServer.SASL_PROPS, new SparkSaslClientCallbackHandler(securityMgr));
59+
} catch (IOException e) {
60+
LOG.error("SaslClient: Could not create SaslClient");
61+
saslClient = null;
62+
}
63+
}
64+
65+
/**
66+
* Used to initiate SASL handshake with server.
67+
* @return response to challenge if needed
68+
* @throws IOException
69+
*/
70+
public byte[] firstToken() throws SaslException {
71+
byte[] saslToken = new byte[0];
72+
if (saslClient.hasInitialResponse()) {
73+
LOG.debug("has initial response");
74+
saslToken = saslClient.evaluateChallenge(saslToken);
75+
}
76+
return saslToken;
77+
}
78+
79+
/**
80+
* Determines whether the authentication exchange has completed.
81+
*/
82+
public boolean isComplete() {
83+
return saslClient.isComplete();
84+
}
85+
86+
/**
87+
* Respond to server's SASL token.
88+
* @param saslTokenMessage contains server's SASL token
89+
* @return client's response SASL token
90+
*/
91+
public byte[] saslResponse(byte[] saslTokenMessage) throws SaslException {
92+
try {
93+
byte[] retval = saslClient.evaluateChallenge(saslTokenMessage);
94+
return retval;
95+
} catch (SaslException e) {
96+
LOG.error("saslResponse: Failed to respond to SASL server's token:", e);
97+
throw e;
98+
}
99+
}
100+
101+
/**
102+
* Disposes of any system resources or security-sensitive information the
103+
* SaslClient might be using.
104+
*/
105+
public void dispose() throws SaslException {
106+
if (saslClient != null) {
107+
try {
108+
saslClient.dispose();
109+
saslClient = null;
110+
} catch (SaslException ignored) {
111+
}
112+
}
113+
}
114+
115+
/**
116+
* Implementation of javax.security.auth.callback.CallbackHandler
117+
* that works with share secrets.
118+
*/
119+
private static class SparkSaslClientCallbackHandler implements CallbackHandler {
120+
private final String userName;
121+
private final char[] userPassword;
122+
123+
/**
124+
* Constructor
125+
*/
126+
public SparkSaslClientCallbackHandler(SecurityManager securityMgr) {
127+
this.userName = SparkSaslServer.
128+
encodeIdentifier(securityMgr.getSaslUser().getBytes());
129+
String secretKey = securityMgr.getSecretKey() ;
130+
String passwd = (secretKey != null) ? secretKey : "";
131+
this.userPassword = SparkSaslServer.encodePassword(passwd.getBytes());
132+
}
133+
134+
/**
135+
* Implementation used to respond to SASL tokens from server.
136+
*
137+
* @param callbacks objects that indicate what credential information the
138+
* server's SaslServer requires from the client.
139+
* @throws UnsupportedCallbackException
140+
*/
141+
public void handle(Callback[] callbacks)
142+
throws UnsupportedCallbackException {
143+
NameCallback nc = null;
144+
PasswordCallback pc = null;
145+
RealmCallback rc = null;
146+
for (Callback callback : callbacks) {
147+
if (callback instanceof RealmChoiceCallback) {
148+
continue;
149+
} else if (callback instanceof NameCallback) {
150+
nc = (NameCallback) callback;
151+
} else if (callback instanceof PasswordCallback) {
152+
pc = (PasswordCallback) callback;
153+
} else if (callback instanceof RealmCallback) {
154+
rc = (RealmCallback) callback;
155+
} else {
156+
throw new UnsupportedCallbackException(callback,
157+
"handle: Unrecognized SASL client callback");
158+
}
159+
}
160+
if (nc != null) {
161+
if (LOG.isDebugEnabled()) {
162+
LOG.debug("handle: SASL client callback: setting username: " +
163+
userName);
164+
}
165+
nc.setName(userName);
166+
}
167+
if (pc != null) {
168+
if (LOG.isDebugEnabled()) {
169+
LOG.debug("handle: SASL client callback: setting userPassword");
170+
}
171+
pc.setPassword(userPassword);
172+
}
173+
if (rc != null) {
174+
if (LOG.isDebugEnabled()) {
175+
LOG.debug("handle: SASL client callback: setting realm: " +
176+
rc.getDefaultText());
177+
}
178+
rc.setText(rc.getDefaultText());
179+
}
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)