or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdauth.mdconfig.mddiff.mdindex.mdobjects.mdreferences.mdremotes.mdrepository.mdstaging.md

auth.mddocs/

0

# Authentication

1

2

Credential management for Git operations supporting various authentication methods including SSH keys, username/password, and SSH agent. Provides secure authentication for remote operations with flexible credential providers.

3

4

## Capabilities

5

6

### Credential Types

7

8

Different credential types for various authentication scenarios.

9

10

```python { .api }

11

class Username:

12

def __init__(self, username: str):

13

"""

14

Username-only credentials.

15

16

Parameters:

17

- username: Username for authentication

18

"""

19

20

class UserPass:

21

def __init__(self, username: str, password: str):

22

"""

23

Username and password credentials.

24

25

Parameters:

26

- username: Username for authentication

27

- password: Password or personal access token

28

"""

29

30

class Keypair:

31

def __init__(

32

self,

33

username: str,

34

pubkey_path: str,

35

privkey_path: str,

36

passphrase: str = ''

37

):

38

"""

39

SSH key pair credentials from files.

40

41

Parameters:

42

- username: Username for SSH authentication (usually 'git')

43

- pubkey_path: Path to public key file

44

- privkey_path: Path to private key file

45

- passphrase: Private key passphrase (empty if none)

46

"""

47

48

class KeypairFromAgent:

49

def __init__(self, username: str):

50

"""

51

SSH key pair credentials from SSH agent.

52

53

Parameters:

54

- username: Username for SSH authentication (usually 'git')

55

"""

56

57

class KeypairFromMemory:

58

def __init__(

59

self,

60

username: str,

61

pubkey_data: str,

62

privkey_data: str,

63

passphrase: str = ''

64

):

65

"""

66

SSH key pair credentials from memory.

67

68

Parameters:

69

- username: Username for SSH authentication

70

- pubkey_data: Public key data as string

71

- privkey_data: Private key data as string

72

- passphrase: Private key passphrase (empty if none)

73

"""

74

```

75

76

### Credential Type Constants

77

78

Constants for identifying credential types in authentication callbacks.

79

80

```python { .api }

81

# Credential Type Flags

82

GIT_CREDENTIAL_USERPASS_PLAINTEXT: int # Username/password

83

GIT_CREDENTIAL_SSH_KEY: int # SSH key pair

84

GIT_CREDENTIAL_SSH_CUSTOM: int # Custom SSH authentication

85

GIT_CREDENTIAL_DEFAULT: int # Default credentials

86

GIT_CREDENTIAL_SSH_INTERACTIVE: int # Interactive SSH

87

GIT_CREDENTIAL_USERNAME: int # Username only

88

GIT_CREDENTIAL_SSH_MEMORY: int # SSH key from memory

89

```

90

91

### Credential Helper Functions

92

93

Utility functions for credential management.

94

95

```python { .api }

96

def get_credentials(

97

url: str,

98

username_from_url: str,

99

allowed_types: int

100

):

101

"""

102

Default credential provider function.

103

104

Parameters:

105

- url: Remote URL requesting credentials

106

- username_from_url: Username extracted from URL

107

- allowed_types: Bitfield of allowed credential types

108

109

Returns:

110

Appropriate credential object or None

111

"""

112

```

113

114

### Authentication in Remote Operations

115

116

Authentication is typically handled through RemoteCallbacks credential method.

117

118

```python { .api }

119

class RemoteCallbacks:

120

def credentials(

121

self,

122

url: str,

123

username_from_url: str,

124

allowed_types: int

125

):

126

"""

127

Provide credentials for remote operation.

128

129

Parameters:

130

- url: Remote URL needing authentication

131

- username_from_url: Username from URL (if any)

132

- allowed_types: Credential types allowed by remote

133

134

Returns:

135

Credential object matching allowed types

136

"""

137

return None

138

139

def certificate_check(

140

self,

141

certificate,

142

valid: bool,

143

host: str

144

) -> bool:

145

"""

146

Verify server certificate for HTTPS.

147

148

Parameters:

149

- certificate: Server certificate

150

- valid: True if certificate passed basic validation

151

- host: Hostname being connected to

152

153

Returns:

154

True to accept certificate, False to reject

155

"""

156

return valid

157

```

158

159

### Usage Examples

160

161

#### SSH Key Authentication

162

163

```python

164

import pygit2

165

166

# SSH key from files

167

class SSHKeyCallbacks(pygit2.RemoteCallbacks):

168

def credentials(self, url, username_from_url, allowed_types):

169

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

170

return pygit2.Keypair(

171

'git',

172

'/home/user/.ssh/id_rsa.pub',

173

'/home/user/.ssh/id_rsa',

174

'my_passphrase' # Empty string if no passphrase

175

)

176

return None

177

178

# Use with remote operations

179

repo = pygit2.Repository('/path/to/repo')

180

callbacks = SSHKeyCallbacks()

181

origin = repo.remotes['origin']

182

origin.fetch(callbacks=callbacks)

183

```

184

185

#### SSH Agent Authentication

186

187

```python

188

# Use SSH agent for key management

189

class SSHAgentCallbacks(pygit2.RemoteCallbacks):

190

def credentials(self, url, username_from_url, allowed_types):

191

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

192

return pygit2.KeypairFromAgent('git')

193

return None

194

195

callbacks = SSHAgentCallbacks()

196

origin.fetch(callbacks=callbacks)

197

```

198

199

#### Username/Password Authentication

200

201

```python

202

# HTTPS with username/password

203

class HTTPSCallbacks(pygit2.RemoteCallbacks):

204

def credentials(self, url, username_from_url, allowed_types):

205

if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:

206

# For GitHub, use personal access token as password

207

return pygit2.UserPass('username', 'personal_access_token')

208

return None

209

210

callbacks = HTTPSCallbacks()

211

origin.push(['refs/heads/main'], callbacks=callbacks)

212

```

213

214

#### Multi-Method Authentication

215

216

```python

217

# Support multiple authentication methods

218

class FlexibleCallbacks(pygit2.RemoteCallbacks):

219

def __init__(self, ssh_key_path=None, username=None, password=None):

220

self.ssh_key_path = ssh_key_path

221

self.username = username

222

self.password = password

223

224

def credentials(self, url, username_from_url, allowed_types):

225

# Try SSH key first

226

if (allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY and

227

self.ssh_key_path):

228

return pygit2.Keypair(

229

'git',

230

f'{self.ssh_key_path}.pub',

231

self.ssh_key_path,

232

''

233

)

234

235

# Try SSH agent

236

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

237

return pygit2.KeypairFromAgent('git')

238

239

# Try username/password

240

if (allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT and

241

self.username and self.password):

242

return pygit2.UserPass(self.username, self.password)

243

244

# Try username only

245

if (allowed_types & pygit2.GIT_CREDENTIAL_USERNAME and

246

self.username):

247

return pygit2.Username(self.username)

248

249

return None

250

251

# Use flexible authentication

252

callbacks = FlexibleCallbacks(

253

ssh_key_path='/home/user/.ssh/id_rsa',

254

username='myuser',

255

password='mytoken'

256

)

257

```

258

259

#### In-Memory SSH Keys

260

261

```python

262

# Load SSH keys from strings (useful for CI/CD)

263

class MemoryKeyCallbacks(pygit2.RemoteCallbacks):

264

def __init__(self, private_key_data, public_key_data, passphrase=''):

265

self.private_key_data = private_key_data

266

self.public_key_data = public_key_data

267

self.passphrase = passphrase

268

269

def credentials(self, url, username_from_url, allowed_types):

270

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

271

return pygit2.KeypairFromMemory(

272

'git',

273

self.public_key_data,

274

self.private_key_data,

275

self.passphrase

276

)

277

return None

278

279

# Read keys from environment or config

280

import os

281

private_key = os.environ.get('SSH_PRIVATE_KEY')

282

public_key = os.environ.get('SSH_PUBLIC_KEY')

283

284

if private_key and public_key:

285

callbacks = MemoryKeyCallbacks(private_key, public_key)

286

origin.fetch(callbacks=callbacks)

287

```

288

289

#### Certificate Verification

290

291

```python

292

# Custom certificate verification

293

class SecureCallbacks(pygit2.RemoteCallbacks):

294

def certificate_check(self, certificate, valid, host):

295

# Always verify certificates in production

296

if not valid:

297

print(f"Invalid certificate for {host}")

298

return False

299

300

# Additional custom verification

301

if 'github.com' in host:

302

# Accept GitHub certificates

303

return True

304

elif 'company.com' in host:

305

# Custom verification for company servers

306

return self.verify_company_cert(certificate)

307

308

# Default to system validation

309

return valid

310

311

def verify_company_cert(self, certificate):

312

# Custom certificate verification logic

313

return True

314

315

def credentials(self, url, username_from_url, allowed_types):

316

if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:

317

return pygit2.UserPass('user', 'token')

318

return None

319

```

320

321

#### Environment-Based Authentication

322

323

```python

324

import os

325

326

class EnvironmentCallbacks(pygit2.RemoteCallbacks):

327

def credentials(self, url, username_from_url, allowed_types):

328

# SSH key from environment

329

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

330

ssh_key = os.environ.get('GIT_SSH_KEY')

331

if ssh_key:

332

public_key = ssh_key + '.pub'

333

if os.path.exists(ssh_key) and os.path.exists(public_key):

334

passphrase = os.environ.get('GIT_SSH_PASSPHRASE', '')

335

return pygit2.Keypair('git', public_key, ssh_key, passphrase)

336

337

# Username/password from environment

338

if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:

339

username = os.environ.get('GIT_USERNAME')

340

password = os.environ.get('GIT_PASSWORD') or os.environ.get('GIT_TOKEN')

341

if username and password:

342

return pygit2.UserPass(username, password)

343

344

return None

345

346

# Use environment-based authentication

347

callbacks = EnvironmentCallbacks()

348

```

349

350

#### Interactive Authentication

351

352

```python

353

import getpass

354

355

class InteractiveCallbacks(pygit2.RemoteCallbacks):

356

def credentials(self, url, username_from_url, allowed_types):

357

print(f"Authentication required for {url}")

358

359

# SSH key with prompt for passphrase

360

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

361

ssh_key = input("SSH private key path [~/.ssh/id_rsa]: ")

362

if not ssh_key:

363

ssh_key = os.path.expanduser('~/.ssh/id_rsa')

364

365

public_key = ssh_key + '.pub'

366

if os.path.exists(ssh_key) and os.path.exists(public_key):

367

passphrase = getpass.getpass("SSH key passphrase (empty if none): ")

368

return pygit2.Keypair('git', public_key, ssh_key, passphrase)

369

370

# Username/password with prompts

371

if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:

372

username = input(f"Username [{username_from_url}]: ") or username_from_url

373

password = getpass.getpass("Password/Token: ")

374

if username and password:

375

return pygit2.UserPass(username, password)

376

377

return None

378

379

# Note: Only use interactive auth in appropriate contexts

380

callbacks = InteractiveCallbacks()

381

```

382

383

#### Clone with Authentication

384

385

```python

386

# Clone repository with authentication

387

def clone_with_auth(url, path, auth_method='ssh_agent'):

388

if auth_method == 'ssh_agent':

389

callbacks = SSHAgentCallbacks()

390

elif auth_method == 'ssh_key':

391

callbacks = SSHKeyCallbacks()

392

elif auth_method == 'https':

393

callbacks = HTTPSCallbacks()

394

else:

395

callbacks = FlexibleCallbacks()

396

397

try:

398

repo = pygit2.clone_repository(url, path, callbacks=callbacks)

399

print(f"Successfully cloned {url} to {path}")

400

return repo

401

except pygit2.GitError as e:

402

print(f"Clone failed: {e}")

403

return None

404

405

# Clone with different auth methods

406

repo = clone_with_auth('git@github.com:user/repo.git', '/local/path', 'ssh_agent')

407

repo = clone_with_auth('https://github.com/user/repo.git', '/local/path', 'https')

408

```

409

410

#### Authentication Error Handling

411

412

```python

413

class RobustCallbacks(pygit2.RemoteCallbacks):

414

def __init__(self):

415

self.auth_attempts = 0

416

self.max_attempts = 3

417

418

def credentials(self, url, username_from_url, allowed_types):

419

self.auth_attempts += 1

420

421

if self.auth_attempts > self.max_attempts:

422

print("Maximum authentication attempts exceeded")

423

return None

424

425

print(f"Authentication attempt {self.auth_attempts}/{self.max_attempts}")

426

427

# Try different methods based on attempt number

428

if self.auth_attempts == 1 and allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

429

try:

430

return pygit2.KeypairFromAgent('git')

431

except Exception as e:

432

print(f"SSH agent failed: {e}")

433

434

if self.auth_attempts == 2 and allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

435

key_path = os.path.expanduser('~/.ssh/id_rsa')

436

if os.path.exists(key_path):

437

return pygit2.Keypair('git', key_path + '.pub', key_path, '')

438

439

if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:

440

# Final attempt with username/password

441

username = input("Username: ")

442

password = getpass.getpass("Password: ")

443

return pygit2.UserPass(username, password)

444

445

return None

446

447

callbacks = RobustCallbacks()

448

try:

449

origin.fetch(callbacks=callbacks)

450

except pygit2.GitError as e:

451

if "authentication" in str(e).lower():

452

print("Authentication failed after all attempts")

453

else:

454

print(f"Other error: {e}")

455

```