or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

abstract.mdconfig.mdconnection.mdextended.mdindex.mdoperations.md

operations.mddocs/

0

# LDAP Operations

1

2

All standard LDAP operations including search, add, modify, delete, compare, and abandon operations with full control support and multiple response formats.

3

4

## Capabilities

5

6

### Search Operations

7

8

Perform LDAP search operations with various scopes, filters, and result processing options.

9

10

```python { .api }

11

def search(self, search_base, search_filter, search_scope=SUBTREE,

12

dereference_aliases=DEREF_ALWAYS, attributes=None, size_limit=0,

13

time_limit=0, types_only=False, get_operational_attributes=False,

14

controls=None, paged_size=None, paged_criticality=False,

15

paged_cookie=None):

16

"""

17

Perform LDAP search operation.

18

19

Args:

20

search_base (str): Base DN for search

21

search_filter (str): LDAP search filter (RFC 4515)

22

search_scope (str): Search scope (BASE, LEVEL, SUBTREE)

23

dereference_aliases (str): Alias dereferencing behavior (NEVER, SEARCH, BASE, ALWAYS)

24

attributes (list, optional): Attributes to retrieve (None for all)

25

size_limit (int): Maximum number of entries to return (0 for no limit)

26

time_limit (int): Search time limit in seconds (0 for no limit)

27

types_only (bool): Return attribute types only, not values

28

get_operational_attributes (bool): Include operational attributes

29

controls (list, optional): LDAP controls for search

30

paged_size (int, optional): Page size for paged search

31

paged_criticality (bool): Paged search criticality

32

paged_cookie (bytes, optional): Paged search cookie

33

34

Returns:

35

bool: True if search successful, False otherwise

36

"""

37

```

38

39

**Search Result Access**:

40

- `connection.entries`: List of Entry objects (abstract layer)

41

- `connection.response`: Raw LDAP response

42

- `connection.result`: Operation result information

43

44

### Add Operations

45

46

Add new entries to the LDAP directory with specified object classes and attributes.

47

48

```python { .api }

49

def add(self, dn, object_class=None, attributes=None, controls=None):

50

"""

51

Add new entry to LDAP directory.

52

53

Args:

54

dn (str): Distinguished Name of new entry

55

object_class (str or list, optional): Object class(es) for entry

56

attributes (dict, optional): Entry attributes as {name: value} or {name: [values]}

57

controls (list, optional): LDAP controls for add operation

58

59

Returns:

60

bool: True if add successful, False otherwise

61

"""

62

```

63

64

### Modify Operations

65

66

Modify existing LDAP entries by adding, deleting, replacing, or incrementing attribute values.

67

68

```python { .api }

69

def modify(self, dn, changes, controls=None):

70

"""

71

Modify existing LDAP entry.

72

73

Args:

74

dn (str): Distinguished Name of entry to modify

75

changes (dict): Modifications as {attribute: [(operation, [values])]}

76

Operation: MODIFY_ADD, MODIFY_DELETE, MODIFY_REPLACE, MODIFY_INCREMENT

77

controls (list, optional): LDAP controls for modify operation

78

79

Returns:

80

bool: True if modify successful, False otherwise

81

"""

82

```

83

84

### Delete Operations

85

86

Delete entries from the LDAP directory.

87

88

```python { .api }

89

def delete(self, dn, controls=None):

90

"""

91

Delete entry from LDAP directory.

92

93

Args:

94

dn (str): Distinguished Name of entry to delete

95

controls (list, optional): LDAP controls for delete operation

96

97

Returns:

98

bool: True if delete successful, False otherwise

99

"""

100

```

101

102

### Modify DN Operations

103

104

Rename or move LDAP entries by modifying their distinguished names.

105

106

```python { .api }

107

def modify_dn(self, dn, relative_dn, delete_old_dn=True, new_superior=None, controls=None):

108

"""

109

Modify distinguished name of entry (rename/move).

110

111

Args:

112

dn (str): Current distinguished name

113

relative_dn (str): New relative distinguished name

114

delete_old_dn (bool): Delete old RDN attribute values

115

new_superior (str, optional): New parent DN for move operation

116

controls (list, optional): LDAP controls for modify DN operation

117

118

Returns:

119

bool: True if modify DN successful, False otherwise

120

"""

121

```

122

123

### Compare Operations

124

125

Compare attribute values in LDAP entries without retrieving the actual values.

126

127

```python { .api }

128

def compare(self, dn, attribute, value, controls=None):

129

"""

130

Compare attribute value in LDAP entry.

131

132

Args:

133

dn (str): Distinguished Name of entry

134

attribute (str): Attribute name to compare

135

value (str or bytes): Value to compare against

136

controls (list, optional): LDAP controls for compare operation

137

138

Returns:

139

bool: True if values match, False if different or error

140

"""

141

```

142

143

### Abandon Operations

144

145

Abandon ongoing LDAP operations using their message IDs.

146

147

```python { .api }

148

def abandon(self, message_id, controls=None):

149

"""

150

Abandon ongoing LDAP operation.

151

152

Args:

153

message_id (int): Message ID of operation to abandon

154

controls (list, optional): LDAP controls for abandon operation

155

156

Returns:

157

bool: True if abandon request sent successfully

158

"""

159

```

160

161

### Extended Operations

162

163

Perform LDAP extended operations with custom request names and values.

164

165

```python { .api }

166

def extended(self, request_name, request_value=None, controls=None):

167

"""

168

Perform LDAP extended operation.

169

170

Args:

171

request_name (str): Extended operation request name (OID)

172

request_value (bytes, optional): Extended operation request value

173

controls (list, optional): LDAP controls for extended operation

174

175

Returns:

176

bool: True if extended operation successful

177

"""

178

```

179

180

### Response Processing

181

182

Access and process LDAP operation responses in various formats.

183

184

```python { .api }

185

def response_to_ldif(self):

186

"""

187

Convert last response to LDIF format.

188

189

Returns:

190

str: Response in LDIF format

191

"""

192

193

def response_to_json(self):

194

"""

195

Convert last response to JSON format.

196

197

Returns:

198

str: Response in JSON format

199

"""

200

201

def response_to_file(self, target, raw=False):

202

"""

203

Save response to file.

204

205

Args:

206

target (str): Target file path

207

raw (bool): Save raw response vs formatted

208

"""

209

```

210

211

## Usage Examples

212

213

### Basic Search

214

215

```python

216

import ldap3

217

218

server = ldap3.Server('ldap://ldap.example.com')

219

conn = ldap3.Connection(server, 'cn=user,dc=example,dc=com', 'password', auto_bind=True)

220

221

# Search for all people

222

conn.search('dc=example,dc=com', '(objectClass=person)', attributes=['cn', 'mail', 'telephoneNumber'])

223

224

for entry in conn.entries:

225

print(f"Name: {entry.cn}")

226

print(f"Email: {entry.mail}")

227

print(f"Phone: {entry.telephoneNumber}")

228

print("---")

229

```

230

231

### Advanced Search with Filters

232

233

```python

234

# Complex search filter

235

filter_str = '(&(objectClass=person)(|(cn=John*)(mail=*@example.com)))'

236

conn.search('ou=people,dc=example,dc=com', filter_str,

237

search_scope=ldap3.LEVEL,

238

attributes=['cn', 'mail', 'description'],

239

size_limit=100)

240

241

# Access raw response

242

for response_item in conn.response:

243

if response_item['type'] == 'searchResEntry':

244

dn = response_item['dn']

245

attributes = response_item['attributes']

246

print(f"DN: {dn}")

247

print(f"Attributes: {attributes}")

248

```

249

250

### Paged Search for Large Results

251

252

```python

253

# Paged search to handle large result sets

254

search_base = 'dc=example,dc=com'

255

search_filter = '(objectClass=person)'

256

search_paged_size = 100

257

258

# Perform first page

259

conn.search(search_base, search_filter, paged_size=search_paged_size)

260

total_entries = len(conn.entries)

261

262

# Continue with additional pages

263

while True:

264

cookie = conn.result['controls']['1.2.840.113556.1.4.319']['value']['cookie']

265

if not cookie:

266

break

267

268

conn.search(search_base, search_filter, paged_size=search_paged_size, paged_cookie=cookie)

269

total_entries += len(conn.entries)

270

271

print(f"Total entries found: {total_entries}")

272

```

273

274

### Adding Entries

275

276

```python

277

# Add new person entry

278

new_dn = 'cn=John Doe,ou=people,dc=example,dc=com'

279

attributes = {

280

'cn': 'John Doe',

281

'sn': 'Doe',

282

'givenName': 'John',

283

'mail': 'john.doe@example.com',

284

'telephoneNumber': '+1-555-1234',

285

'userPassword': 'secretpassword'

286

}

287

288

result = conn.add(new_dn, object_class=['inetOrgPerson', 'person'], attributes=attributes)

289

if result:

290

print("Entry added successfully")

291

else:

292

print(f"Failed to add entry: {conn.result}")

293

```

294

295

### Modifying Entries

296

297

```python

298

# Modify existing entry

299

target_dn = 'cn=John Doe,ou=people,dc=example,dc=com'

300

301

# Different types of modifications

302

changes = {

303

'mail': [(ldap3.MODIFY_REPLACE, 'newemail@example.com')], # Replace email

304

'telephoneNumber': [(ldap3.MODIFY_ADD, '+1-555-5678')], # Add phone number

305

'description': [(ldap3.MODIFY_DELETE, [])], # Delete all descriptions

306

'loginCount': [(ldap3.MODIFY_INCREMENT, 1)] # Increment counter

307

}

308

309

result = conn.modify(target_dn, changes)

310

if result:

311

print("Entry modified successfully")

312

else:

313

print(f"Failed to modify entry: {conn.result}")

314

```

315

316

### Complex Modify with Multiple Changes

317

318

```python

319

# Multiple attribute modifications in single operation

320

changes = {

321

'mail': [(ldap3.MODIFY_REPLACE, ['primary@example.com', 'secondary@example.com'])],

322

'telephoneNumber': [(ldap3.MODIFY_DELETE, '+1-555-1234'), # Delete specific phone

323

(ldap3.MODIFY_ADD, ['+1-555-9999', '+1-555-8888'])], # Add new phones

324

'title': [(ldap3.MODIFY_REPLACE, 'Senior Developer')]

325

}

326

327

conn.modify('cn=John Doe,ou=people,dc=example,dc=com', changes)

328

```

329

330

### Moving/Renaming Entries

331

332

```python

333

# Rename entry (change CN)

334

old_dn = 'cn=John Doe,ou=people,dc=example,dc=com'

335

new_rdn = 'cn=John Smith'

336

conn.modify_dn(old_dn, new_rdn, delete_old_dn=True)

337

338

# Move entry to different OU

339

current_dn = 'cn=John Smith,ou=people,dc=example,dc=com'

340

new_superior = 'ou=employees,dc=example,dc=com'

341

conn.modify_dn(current_dn, 'cn=John Smith', new_superior=new_superior)

342

```

343

344

### Deleting Entries

345

346

```python

347

# Delete single entry

348

entry_dn = 'cn=John Smith,ou=employees,dc=example,dc=com'

349

result = conn.delete(entry_dn)

350

if result:

351

print("Entry deleted successfully")

352

else:

353

print(f"Failed to delete entry: {conn.result}")

354

```

355

356

### Compare Operation

357

358

```python

359

# Compare attribute value without retrieving it

360

entry_dn = 'cn=admin,dc=example,dc=com'

361

result = conn.compare(entry_dn, 'userPassword', 'secretpassword')

362

if result:

363

print("Password matches")

364

elif conn.result['result'] == 5: # RESULT_COMPARE_FALSE

365

print("Password does not match")

366

else:

367

print(f"Compare operation failed: {conn.result}")

368

```

369

370

### Working with Controls

371

372

```python

373

# Search with server-side sorting control

374

from ldap3.protocol.rfc2696 import paged_search_control

375

from ldap3.protocol.rfc2891 import sort_control

376

377

# Server-side sort by cn attribute

378

sort_ctrl = sort_control([('cn', True)]) # True = ascending

379

conn.search('dc=example,dc=com', '(objectClass=person)',

380

controls=[sort_ctrl], attributes=['cn', 'mail'])

381

382

# Process sorted results

383

for entry in conn.entries:

384

print(f"{entry.cn}: {entry.mail}")

385

```

386

387

### Asynchronous Operations

388

389

```python

390

# Asynchronous connection for non-blocking operations

391

server = ldap3.Server('ldap://ldap.example.com')

392

conn = ldap3.Connection(server, 'cn=user,dc=example,dc=com', 'password',

393

client_strategy=ldap3.ASYNC, auto_bind=True)

394

395

# Start search operation (returns immediately)

396

message_id = conn.search('dc=example,dc=com', '(objectClass=person)')

397

398

# Do other work while search is running

399

import time

400

time.sleep(1)

401

402

# Get results when ready

403

result, response = conn.get_response(message_id)

404

if result:

405

for item in response:

406

if item['type'] == 'searchResEntry':

407

print(f"Found: {item['dn']}")

408

```

409

410

### Response Format Examples

411

412

```python

413

# JSON response format

414

conn.search('dc=example,dc=com', '(objectClass=person)', attributes=['cn', 'mail'])

415

json_response = conn.response_to_json()

416

print(json_response)

417

418

# LDIF response format

419

ldif_response = conn.response_to_ldif()

420

print(ldif_response)

421

422

# Save to file

423

conn.response_to_file('/tmp/search_results.ldif')

424

```