or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdauthorities.mdcontext-management.mdembedded-server.mdindex.mdjson-serialization.mdpassword-policy.mduser-details.md

embedded-server.mddocs/

0

# Embedded Server Support

1

2

Embedded LDAP server containers for testing and development environments with support for Apache Directory Server and UnboundID implementations.

3

4

## Capabilities

5

6

### EmbeddedLdapServerContainer

7

8

Base interface for embedded LDAP server containers.

9

10

```java { .api }

11

/**

12

* Base interface for embedded LDAP server containers providing common lifecycle operations

13

*/

14

public interface EmbeddedLdapServerContainer {

15

/**

16

* Gets the port number the embedded server is listening on

17

* @return the LDAP port number

18

*/

19

int getPort();

20

21

/**

22

* Sets the port number for the embedded LDAP server

23

* @param port the port number to use

24

*/

25

void setPort(int port);

26

27

/**

28

* Starts the embedded LDAP server

29

* @throws Exception if server startup fails

30

*/

31

void start() throws Exception;

32

33

/**

34

* Stops the embedded LDAP server

35

* @throws Exception if server shutdown fails

36

*/

37

void stop() throws Exception;

38

39

/**

40

* Checks if the embedded server is currently running

41

* @return true if the server is running

42

*/

43

boolean isRunning();

44

}

45

```

46

47

### ApacheDSContainer

48

49

Embedded Apache Directory Server container for testing and development with Spring Security LDAP.

50

51

```java { .api }

52

/**

53

* Embedded Apache Directory Server container providing LDAP server functionality

54

* for testing and development environments

55

*/

56

public class ApacheDSContainer implements InitializingBean, DisposableBean, Lifecycle {

57

/**

58

* Creates an Apache DS container with root DN and LDIF data

59

* @param root the root DN for the directory (e.g., "dc=springframework,dc=org")

60

* @param ldifs comma-separated list of LDIF file paths to load

61

*/

62

public ApacheDSContainer(String root, String ldifs);

63

64

/**

65

* Starts the embedded Apache Directory Server

66

* @throws Exception if server startup fails

67

*/

68

public void start() throws Exception;

69

70

/**

71

* Stops the embedded Apache Directory Server

72

* @throws Exception if server shutdown fails

73

*/

74

public void stop() throws Exception;

75

76

/**

77

* Checks if the server is currently running

78

* @return true if server is running

79

*/

80

public boolean isRunning();

81

82

/**

83

* Gets the port number the server is listening on

84

* @return the LDAP port number

85

*/

86

public int getPort();

87

88

/**

89

* Sets the port number for the LDAP server

90

* @param port the port number (default: random available port)

91

*/

92

public void setPort(int port);

93

94

/**

95

* Sets additional Apache DS configuration

96

* @param ldifFile path to LDIF file containing additional configuration

97

*/

98

public void setLdifFile(String ldifFile);

99

100

/**

101

* Sets the working directory for the server

102

* @param workingDirectory the working directory path

103

*/

104

public void setWorkingDirectory(String workingDirectory);

105

106

/**

107

* Performs initialization after properties are set

108

*/

109

public void afterPropertiesSet() throws Exception;

110

111

/**

112

* Cleanup resources when bean is destroyed

113

*/

114

public void destroy() throws Exception;

115

}

116

```

117

118

**Usage Examples:**

119

120

```java

121

// Basic Apache DS container setup

122

ApacheDSContainer container = new ApacheDSContainer("dc=springframework,dc=org",

123

"classpath:test-data.ldif");

124

container.setPort(33389);

125

container.start();

126

127

// With custom working directory

128

container.setWorkingDirectory("target/apacheds-work");

129

130

// Lifecycle management

131

container.afterPropertiesSet();

132

// ... use the server for testing

133

container.destroy();

134

```

135

136

### UnboundIdContainer

137

138

Embedded UnboundID LDAP server container offering high performance for testing scenarios.

139

140

```java { .api }

141

/**

142

* Embedded UnboundID LDAP server container providing high-performance LDAP server

143

* functionality for testing and development environments

144

*/

145

public class UnboundIdContainer implements InitializingBean, DisposableBean, Lifecycle {

146

/**

147

* Creates an UnboundID container with root DN and LDIF data

148

* @param root the root DN for the directory

149

* @param ldif path to LDIF file containing initial data

150

*/

151

public UnboundIdContainer(String root, String ldif);

152

153

/**

154

* Starts the embedded UnboundID LDAP server

155

* @throws Exception if server startup fails

156

*/

157

public void start() throws Exception;

158

159

/**

160

* Stops the embedded UnboundID LDAP server

161

* @throws Exception if server shutdown fails

162

*/

163

public void stop() throws Exception;

164

165

/**

166

* Checks if the server is currently running

167

* @return true if server is running

168

*/

169

public boolean isRunning();

170

171

/**

172

* Gets the port number the server is listening on

173

* @return the LDAP port number

174

*/

175

public int getPort();

176

177

/**

178

* Sets the port number for the LDAP server

179

* @param port the port number (default: random available port)

180

*/

181

public void setPort(int port);

182

183

/**

184

* Sets the manager distinguished name for administrative operations

185

* @param managerDn the manager DN (e.g., "cn=Directory Manager")

186

*/

187

public void setManagerDn(String managerDn);

188

189

/**

190

* Sets the manager password for administrative operations

191

* @param managerPassword the manager password

192

*/

193

public void setManagerPassword(String managerPassword);

194

195

/**

196

* Performs initialization after properties are set

197

*/

198

public void afterPropertiesSet() throws Exception;

199

200

/**

201

* Cleanup resources when bean is destroyed

202

*/

203

public void destroy() throws Exception;

204

}

205

```

206

207

**Usage Examples:**

208

209

```java

210

// Basic UnboundID container setup

211

UnboundIdContainer container = new UnboundIdContainer("dc=springframework,dc=org",

212

"classpath:test-users.ldif");

213

container.setPort(33389);

214

container.setManagerDn("cn=Directory Manager");

215

container.setManagerPassword("password");

216

container.start();

217

218

// Lifecycle management in tests

219

@BeforeEach

220

void setUp() throws Exception {

221

container.afterPropertiesSet();

222

container.start();

223

}

224

225

@AfterEach

226

void tearDown() throws Exception {

227

container.stop();

228

container.destroy();

229

}

230

```

231

232

## Test Configuration Examples

233

234

### Spring Test Configuration with Embedded Server

235

236

```java

237

@TestConfiguration

238

@Profile("embedded-ldap")

239

public class EmbeddedLdapConfig {

240

241

@Bean

242

@Primary

243

public UnboundIdContainer embeddedLdapServer() {

244

UnboundIdContainer container = new UnboundIdContainer(

245

"dc=springframework,dc=org",

246

"classpath:test-ldap-data.ldif"

247

);

248

container.setPort(0); // Use random available port

249

container.setManagerDn("cn=Directory Manager");

250

container.setManagerPassword("password");

251

return container;

252

}

253

254

@Bean

255

@Primary

256

@DependsOn("embeddedLdapServer")

257

public DefaultSpringSecurityContextSource embeddedContextSource() {

258

int port = embeddedLdapServer().getPort();

259

DefaultSpringSecurityContextSource contextSource =

260

new DefaultSpringSecurityContextSource("ldap://localhost:" + port + "/dc=springframework,dc=org");

261

contextSource.setUserDn("cn=Directory Manager");

262

contextSource.setPassword("password");

263

return contextSource;

264

}

265

}

266

```

267

268

### JUnit 5 Test with Embedded LDAP

269

270

```java

271

@SpringBootTest

272

@ActiveProfiles("embedded-ldap")

273

class LdapAuthenticationTest {

274

275

@Autowired

276

private UnboundIdContainer embeddedLdapServer;

277

278

@Autowired

279

private LdapAuthenticationProvider authenticationProvider;

280

281

@Test

282

void shouldAuthenticateValidUser() {

283

// Given

284

UsernamePasswordAuthenticationToken token =

285

new UsernamePasswordAuthenticationToken("john", "password");

286

287

// When

288

Authentication result = authenticationProvider.authenticate(token);

289

290

// Then

291

assertThat(result.isAuthenticated()).isTrue();

292

assertThat(result.getName()).isEqualTo("john");

293

assertThat(result.getAuthorities()).hasSize(2);

294

}

295

}

296

```

297

298

### Integration Test Setup

299

300

```java

301

@ExtendWith(SpringExtension.class)

302

@ContextConfiguration(classes = {EmbeddedLdapConfig.class, LdapSecurityConfig.class})

303

class LdapIntegrationTest {

304

305

@Autowired

306

private ApacheDSContainer ldapServer;

307

308

@Autowired

309

private LdapUserDetailsService userDetailsService;

310

311

@BeforeEach

312

void startLdapServer() throws Exception {

313

if (!ldapServer.isRunning()) {

314

ldapServer.start();

315

}

316

}

317

318

@AfterEach

319

void stopLdapServer() throws Exception {

320

if (ldapServer.isRunning()) {

321

ldapServer.stop();

322

}

323

}

324

325

@Test

326

void shouldLoadUserDetails() {

327

UserDetails user = userDetailsService.loadUserByUsername("alice");

328

329

assertThat(user).isNotNull();

330

assertThat(user.getUsername()).isEqualTo("alice");

331

assertThat(user.getAuthorities()).isNotEmpty();

332

}

333

}

334

```

335

336

## LDIF Data Examples

337

338

### Sample LDIF for Testing

339

340

```ldif

341

# test-ldap-data.ldif

342

dn: dc=springframework,dc=org

343

objectClass: top

344

objectClass: domain

345

objectClass: extensibleObject

346

dc: springframework

347

348

dn: ou=people,dc=springframework,dc=org

349

objectClass: top

350

objectClass: organizationalUnit

351

ou: people

352

353

dn: ou=groups,dc=springframework,dc=org

354

objectClass: top

355

objectClass: organizationalUnit

356

ou: groups

357

358

# Users

359

dn: uid=john,ou=people,dc=springframework,dc=org

360

objectClass: top

361

objectClass: person

362

objectClass: organizationalPerson

363

objectClass: inetOrgPerson

364

uid: john

365

cn: John Smith

366

sn: Smith

367

mail: john@springframework.org

368

userPassword: password

369

370

dn: uid=alice,ou=people,dc=springframework,dc=org

371

objectClass: top

372

objectClass: person

373

objectClass: organizationalPerson

374

objectClass: inetOrgPerson

375

uid: alice

376

cn: Alice Johnson

377

sn: Johnson

378

mail: alice@springframework.org

379

userPassword: secret

380

381

# Groups

382

dn: cn=users,ou=groups,dc=springframework,dc=org

383

objectClass: top

384

objectClass: groupOfNames

385

cn: users

386

member: uid=john,ou=people,dc=springframework,dc=org

387

member: uid=alice,ou=people,dc=springframework,dc=org

388

389

dn: cn=admins,ou=groups,dc=springframework,dc=org

390

objectClass: top

391

objectClass: groupOfNames

392

cn: admins

393

member: uid=alice,ou=people,dc=springframework,dc=org

394

```

395

396

### Complex Test Data Structure

397

398

```java

399

@TestConfiguration

400

public class LdapTestDataConfig {

401

402

@Bean

403

public UnboundIdContainer ldapServerWithComplexData() {

404

UnboundIdContainer container = new UnboundIdContainer(

405

"dc=example,dc=com",

406

"classpath:complex-ldap-structure.ldif"

407

);

408

409

// Configure for complex scenarios

410

container.setPort(0);

411

container.setManagerDn("cn=Directory Manager");

412

container.setManagerPassword("admin123");

413

414

return container;

415

}

416

417

// Bean that loads additional test data after server start

418

@Bean

419

@DependsOn("ldapServerWithComplexData")

420

public LdapTestDataLoader testDataLoader() {

421

return new LdapTestDataLoader(embeddedContextSource());

422

}

423

}

424

425

@Component

426

public class LdapTestDataLoader {

427

428

private final SpringSecurityLdapTemplate ldapTemplate;

429

430

public LdapTestDataLoader(ContextSource contextSource) {

431

this.ldapTemplate = new SpringSecurityLdapTemplate(contextSource);

432

}

433

434

@PostConstruct

435

public void loadAdditionalTestData() {

436

// Add test data programmatically

437

createTestOrganizationalUnits();

438

createTestUsers();

439

createTestGroups();

440

}

441

442

private void createTestOrganizationalUnits() {

443

// Create additional OUs for testing

444

DirContextAdapter context = new DirContextAdapter("ou=departments,dc=example,dc=com");

445

context.setAttributeValues("objectClass", new String[]{"top", "organizationalUnit"});

446

context.setAttributeValue("ou", "departments");

447

ldapTemplate.bind(context);

448

}

449

450

// Additional helper methods for test data creation...

451

}

452

```

453

454

### Performance Testing Configuration

455

456

```java

457

@TestConfiguration

458

@Profile("performance-test")

459

public class PerformanceLdapConfig {

460

461

@Bean

462

public UnboundIdContainer performanceTestLdapServer() {

463

UnboundIdContainer container = new UnboundIdContainer(

464

"dc=perf,dc=test",

465

"classpath:large-dataset.ldif"

466

);

467

468

// Optimize for performance testing

469

container.setPort(33389); // Fixed port for consistency

470

container.setManagerDn("cn=Directory Manager");

471

container.setManagerPassword("admin");

472

473

return container;

474

}

475

476

@Bean

477

@Primary

478

public DefaultSpringSecurityContextSource performanceContextSource() {

479

DefaultSpringSecurityContextSource contextSource =

480

new DefaultSpringSecurityContextSource("ldap://localhost:33389/dc=perf,dc=test");

481

482

// Connection pool settings for performance

483

contextSource.setPooled(true);

484

485

Map<String, Object> baseEnv = new HashMap<>();

486

baseEnv.put("com.sun.jndi.ldap.connect.pool.maxsize", "20");

487

baseEnv.put("com.sun.jndi.ldap.connect.pool.prefsize", "10");

488

baseEnv.put("com.sun.jndi.ldap.connect.pool.timeout", "300000");

489

contextSource.setBaseEnvironmentProperties(baseEnv);

490

491

return contextSource;

492

}

493

}

494

```

495

496

### Docker-based Testing Alternative

497

498

```java

499

@Testcontainers

500

@SpringBootTest

501

class DockerLdapTest {

502

503

@Container

504

static final GenericContainer<?> ldapContainer = new GenericContainer<>("osixia/openldap:1.5.0")

505

.withExposedPorts(389)

506

.withEnv("LDAP_ORGANISATION", "Test Org")

507

.withEnv("LDAP_DOMAIN", "test.org")

508

.withEnv("LDAP_ADMIN_PASSWORD", "admin")

509

.withClasspathResourceMapping("test-data.ldif", "/container/service/slapd/assets/config/bootstrap/ldif/50-bootstrap.ldif", BindMode.READ_ONLY);

510

511

@DynamicPropertySource

512

static void configureProperties(DynamicPropertyRegistry registry) {

513

registry.add("ldap.url", () -> "ldap://localhost:" + ldapContainer.getMappedPort(389));

514

registry.add("ldap.base", () -> "dc=test,dc=org");

515

registry.add("ldap.username", () -> "cn=admin,dc=test,dc=org");

516

registry.add("ldap.password", () -> "admin");

517

}

518

519

@Test

520

void shouldConnectToDockerLdap() {

521

// Test LDAP connectivity and operations

522

assertThat(ldapContainer.isRunning()).isTrue();

523

}

524

}

525

```