or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client.mdhandler.mdindex.mdmesos.mdprotocol.mdresolver.mdsecurity.md

security.mddocs/

0

# Security

1

2

SASL-based authentication system for secure shuffle operations, managing application secrets and authenticating client connections.

3

4

## Capabilities

5

6

### ShuffleSecretManager

7

8

Central component for managing SASL authentication secrets for shuffle operations.

9

10

```java { .api }

11

/**

12

* A class that manages shuffle secret used by the external shuffle service.

13

* Implements SecretKeyHolder for SASL authentication integration.

14

*/

15

public class ShuffleSecretManager implements SecretKeyHolder {

16

/**

17

* Creates a new shuffle secret manager with empty secret map.

18

*/

19

public ShuffleSecretManager();

20

21

/**

22

* Register an application with its secret.

23

* Executors need to first authenticate themselves with the same secret before

24

* fetching shuffle files written by other executors in this application.

25

*

26

* @param appId application identifier

27

* @param shuffleSecret secret key for this application

28

*/

29

public void registerApp(String appId, String shuffleSecret);

30

31

/**

32

* Unregister an application and remove its secret.

33

* Called when application terminates.

34

*

35

* @param appId application identifier

36

*/

37

public void unregisterApp(String appId);

38

39

/**

40

* Get the secret key for a given application.

41

* Implementation of SecretKeyHolder interface for SASL integration.

42

*

43

* @param appId application identifier

44

* @return secret key for the application, or null if not registered

45

*/

46

@Override

47

public String getSecretKey(String appId);

48

49

/**

50

* Get the SASL user for a given application.

51

* Returns the standard Spark SASL user identifier.

52

*

53

* @param appId application identifier (unused, same user for all apps)

54

* @return SASL user identifier ("sparkSaslUser")

55

*/

56

@Override

57

public String getSaslUser(String appId);

58

}

59

```

60

61

**Usage Examples:**

62

63

```java

64

import org.apache.spark.network.sasl.ShuffleSecretManager;

65

66

// Create secret manager

67

ShuffleSecretManager secretManager = new ShuffleSecretManager();

68

69

// Register application secrets

70

String appId1 = "application_1234567890_0001";

71

String secret1 = "app1-secret-key-abcd1234";

72

secretManager.registerApp(appId1, secret1);

73

74

String appId2 = "application_1234567890_0002";

75

String secret2 = "app2-secret-key-efgh5678";

76

secretManager.registerApp(appId2, secret2);

77

78

// Retrieve secrets for authentication

79

String retrievedSecret = secretManager.getSecretKey(appId1);

80

if (retrievedSecret != null) {

81

System.out.println("Secret found for app: " + appId1);

82

// Use secret for SASL authentication

83

} else {

84

System.err.println("No secret registered for app: " + appId1);

85

}

86

87

// Get SASL user (same for all applications)

88

String saslUser = secretManager.getSaslUser(appId1);

89

System.out.println("SASL user: " + saslUser); // Prints: sparkSaslUser

90

91

// Clean up when application terminates

92

secretManager.unregisterApp(appId1);

93

System.out.println("Unregistered app: " + appId1);

94

```

95

96

### SASL Authentication Integration

97

98

The secret manager integrates with Spark's SASL authentication system:

99

100

```java

101

// Integration with ExternalShuffleClient

102

import org.apache.spark.network.sasl.SecretKeyHolder;

103

import org.apache.spark.network.shuffle.ExternalShuffleClient;

104

import org.apache.spark.network.util.TransportConf;

105

106

// Create client with SASL authentication enabled

107

TransportConf conf = new TransportConf("shuffle");

108

ShuffleSecretManager secretManager = new ShuffleSecretManager();

109

110

// Register application secret

111

secretManager.registerApp("myApp", "mySecretKey");

112

113

// Create authenticated client

114

ExternalShuffleClient client = new ExternalShuffleClient(

115

conf,

116

secretManager, // SecretKeyHolder for authentication

117

true // Enable authentication

118

);

119

120

client.init("myApp");

121

// Client will automatically authenticate using registered secret

122

```

123

124

### Server-Side Authentication

125

126

The shuffle service validates client authentication:

127

128

```java

129

import org.apache.spark.network.shuffle.ExternalShuffleBlockHandler;

130

import org.apache.spark.network.client.TransportClient;

131

132

// Server-side authentication check (simplified example)

133

public class AuthenticatedShuffleHandler extends ExternalShuffleBlockHandler {

134

135

private void checkAuth(TransportClient client, String appId) {

136

if (client.getClientId() != null && !client.getClientId().equals(appId)) {

137

throw new SecurityException(String.format(

138

"Client for %s not authorized for application %s.",

139

client.getClientId(), appId));

140

}

141

}

142

143

// Authentication is enforced in message handling

144

protected void handleMessage(BlockTransferMessage msgObj,

145

TransportClient client,

146

RpcResponseCallback callback) {

147

try {

148

if (msgObj instanceof OpenBlocks) {

149

OpenBlocks msg = (OpenBlocks) msgObj;

150

checkAuth(client, msg.appId); // Validate client authorization

151

// Process request...

152

} else if (msgObj instanceof RegisterExecutor) {

153

RegisterExecutor msg = (RegisterExecutor) msgObj;

154

checkAuth(client, msg.appId); // Validate client authorization

155

// Process registration...

156

}

157

} catch (SecurityException e) {

158

callback.onFailure(e); // Return authentication error to client

159

}

160

}

161

}

162

```

163

164

## Security Configuration

165

166

### Transport Configuration for SASL

167

168

```java

169

import org.apache.spark.network.util.TransportConf;

170

import org.apache.spark.network.util.ConfigProvider;

171

172

// Configure transport for SASL authentication

173

ConfigProvider configProvider = new ConfigProvider() {

174

@Override

175

public String get(String name) {

176

switch (name) {

177

case "spark.authenticate":

178

return "true";

179

case "spark.network.sasl.maxEncryptedBlockSize":

180

return "64k";

181

case "spark.network.sasl.serverAlwaysEncrypt":

182

return "true";

183

default:

184

return null;

185

}

186

}

187

188

@Override

189

public Iterable<Map.Entry<String, String>> getAll() {

190

Map<String, String> configs = new HashMap<>();

191

configs.put("spark.authenticate", "true");

192

configs.put("spark.network.sasl.maxEncryptedBlockSize", "64k");

193

configs.put("spark.network.sasl.serverAlwaysEncrypt", "true");

194

return configs.entrySet();

195

}

196

};

197

198

TransportConf conf = new TransportConf("shuffle", configProvider);

199

```

200

201

### Secret Generation and Management

202

203

```java

204

import java.security.SecureRandom;

205

import java.util.Base64;

206

207

/**

208

* Example utility for generating secure shuffle secrets

209

*/

210

public class SecretGenerator {

211

private static final SecureRandom random = new SecureRandom();

212

213

/**

214

* Generates a cryptographically secure random secret.

215

*

216

* @param lengthBytes length of secret in bytes

217

* @return base64-encoded secret string

218

*/

219

public static String generateSecret(int lengthBytes) {

220

byte[] secretBytes = new byte[lengthBytes];

221

random.nextBytes(secretBytes);

222

return Base64.getEncoder().encodeToString(secretBytes);

223

}

224

225

/**

226

* Generates a 256-bit (32 byte) secret suitable for shuffle authentication.

227

*/

228

public static String generateShuffleSecret() {

229

return generateSecret(32);

230

}

231

}

232

233

// Usage example

234

String appId = "application_1234567890_0001";

235

String secret = SecretGenerator.generateShuffleSecret();

236

secretManager.registerApp(appId, secret);

237

System.out.println("Generated secret for " + appId + ": " + secret.substring(0, 8) + "...");

238

```

239

240

## Security Best Practices

241

242

### Secret Lifecycle Management

243

244

```java

245

/**

246

* Example application lifecycle manager with proper secret handling

247

*/

248

public class SecureShuffleLifecycleManager {

249

private final ShuffleSecretManager secretManager;

250

private final Map<String, String> appSecrets;

251

252

public SecureShuffleLifecycleManager() {

253

this.secretManager = new ShuffleSecretManager();

254

this.appSecrets = new ConcurrentHashMap<>();

255

}

256

257

/**

258

* Register application with generated secret

259

*/

260

public void registerApplication(String appId) {

261

// Generate unique secret for this application

262

String secret = SecretGenerator.generateShuffleSecret();

263

264

// Store secret securely (in production, use secure key management)

265

appSecrets.put(appId, secret);

266

secretManager.registerApp(appId, secret);

267

268

System.out.println("Registered application with secure secret: " + appId);

269

}

270

271

/**

272

* Clean up application secrets when application terminates

273

*/

274

public void unregisterApplication(String appId) {

275

// Remove from secret manager

276

secretManager.unregisterApp(appId);

277

278

// Clear secret from memory

279

String secret = appSecrets.remove(appId);

280

if (secret != null) {

281

// Overwrite secret in memory (basic security measure)

282

char[] secretChars = secret.toCharArray();

283

Arrays.fill(secretChars, '\0');

284

}

285

286

System.out.println("Unregistered application and cleared secrets: " + appId);

287

}

288

289

/**

290

* Get secret manager for client configuration

291

*/

292

public ShuffleSecretManager getSecretManager() {

293

return secretManager;

294

}

295

}

296

```

297

298

### Error Handling and Security Logging

299

300

```java

301

/**

302

* Secure error handling with appropriate logging

303

*/

304

public class SecureErrorHandler {

305

private static final Logger logger = LoggerFactory.getLogger(SecureErrorHandler.class);

306

307

public void handleAuthenticationFailure(String appId, String clientId, Exception e) {

308

// Log security events (without exposing secrets)

309

logger.warn("Authentication failed for app {} from client {}: {}",

310

appId, clientId, e.getMessage());

311

312

// In production, consider:

313

// - Rate limiting failed attempts

314

// - Alerting security teams

315

// - Temporary blocking of suspicious clients

316

}

317

318

public void handleSecretRegistration(String appId) {

319

logger.info("Registered shuffle secret for application: {}", appId);

320

// Do NOT log the actual secret value

321

}

322

323

public void handleSecretUnregistration(String appId) {

324

logger.info("Unregistered shuffle secret for application: {}", appId);

325

}

326

}

327

```

328

329

## Common Security Scenarios

330

331

### Client Authentication Flow

332

333

```java

334

// 1. Application registers with shuffle service

335

String appId = "spark-app-123";

336

String secret = generateSecureSecret();

337

shuffleSecretManager.registerApp(appId, secret);

338

339

// 2. Client connects with authentication

340

TransportConf conf = new TransportConf("shuffle");

341

ExternalShuffleClient client = new ExternalShuffleClient(conf, shuffleSecretManager, true);

342

client.init(appId);

343

344

// 3. Client performs authenticated operations

345

try {

346

client.registerWithShuffleServer(host, port, execId, executorInfo);

347

client.fetchBlocks(host, port, execId, blockIds, listener, null);

348

} catch (SecurityException e) {

349

System.err.println("Authentication failed: " + e.getMessage());

350

// Handle authentication failure

351

}

352

```

353

354

### Multi-Application Security

355

356

```java

357

// Managing secrets for multiple applications

358

ShuffleSecretManager secretManager = new ShuffleSecretManager();

359

360

// Register multiple applications with different secrets

361

Map<String, String> appSecrets = new HashMap<>();

362

for (int i = 1; i <= 5; i++) {

363

String appId = "application_" + System.currentTimeMillis() + "_000" + i;

364

String secret = SecretGenerator.generateShuffleSecret();

365

366

secretManager.registerApp(appId, secret);

367

appSecrets.put(appId, secret);

368

369

System.out.println("Registered app " + i + ": " + appId);

370

}

371

372

// Verify secrets are isolated

373

for (String appId : appSecrets.keySet()) {

374

String retrievedSecret = secretManager.getSecretKey(appId);

375

assert retrievedSecret.equals(appSecrets.get(appId)) : "Secret mismatch for " + appId;

376

}

377

378

System.out.println("All application secrets verified");

379

```

380

381

## Error Handling

382

383

Security-related errors that may occur:

384

385

- **SecurityException**: Client authentication failures, unauthorized access attempts

386

- **IllegalArgumentException**: Invalid application IDs, malformed secrets

387

- **NullPointerException**: Missing secrets for registered applications

388

389

**Security Error Handling Example:**

390

391

```java

392

try {

393

String secret = secretManager.getSecretKey(appId);

394

if (secret == null) {

395

throw new SecurityException("No secret registered for application: " + appId);

396

}

397

// Use secret for authentication

398

} catch (SecurityException e) {

399

logger.warn("Security violation: {}", e.getMessage());

400

// Handle security failure appropriately

401

throw e; // Re-throw to caller

402

}

403

```