Auth
pytruenas.auth
__all__ = ['Credentials', 'LocalAuth', 'APIKeyAuth', 'TokenAuth', 'BasicAuth', 'redact_call_args']
module-attribute
APIKeyAuth(api_key, username=None)
Bases: Credentials
Source code in src/pytruenas/auth.py
350 351 352 353 354 355 | |
MECHANISM = 'API_KEY_PLAIN'
class-attribute
instance-attribute
METHOD = 'login_with_api_key'
class-attribute
instance-attribute
api_key = api_key
instance-attribute
username = username
instance-attribute
BasicAuth(username, password, otp=None)
Bases: Credentials
Source code in src/pytruenas/auth.py
388 389 390 391 392 393 | |
MECHANISM = 'PASSWORD_PLAIN'
class-attribute
instance-attribute
METHOD = 'login'
class-attribute
instance-attribute
otp = otp
instance-attribute
password = password
instance-attribute
username = username
instance-attribute
Credentials(*args, **kwargs)
Source code in src/pytruenas/auth.py
181 182 | |
MECHANISM = None
class-attribute
instance-attribute
METHOD = None
class-attribute
instance-attribute
from_env(env=None)
staticmethod
The credentials in $PYTRUENAS_CREDENTIALS (a secret).
Any form Credentials(...) takes as one string; unset or empty is
:class:LocalAuth. env is a mapping to read the variable from in
place of the process environment.
Source code in src/pytruenas/auth.py
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | |
from_host_credentials(username=None, password=None, otp=None, api_key=None, token=None)
staticmethod
Select a credential from an already-parsed credential mapping.
This is the hostctl bridge. hostctl.host.parse_credentials has
already split a URI's password field into the password proper and its
trailing key:value extras -- the OTP arrives here as otp, not
embedded in password. So this method deliberately does no string
parsing: it only picks the matching subclass. Contrast
Credentials(...), which accepts the raw single-string form used by
$PYTRUENAS_CREDENTIALS and credentials=.
Both projects encode an OTP the same way -- a newline after the
password, then otp:<token> -- so the two paths agree on meaning
while splitting the string exactly once, here or in hostctl, never
twice.
A newline is the separator because a password can never contain one:
at an interactive prompt, Enter submits the value rather than being
typed into it. That makes the split free -- no character is stolen from
the password alphabet and no escaping scheme is needed. The one caveat
is transport-specific: a URI cannot carry a raw newline (urlsplit
strips it), so an OTP in a connection string must be percent-encoded as
%0A. See :mod:pytruenas.host.
Precedence when several are supplied: token, then api_key, then
password. They are mutually exclusive mechanisms rather than a
fallback chain, so passing more than one is a caller error; the order
only makes the outcome deterministic rather than arbitrary. With none of
them, this is local-socket auth (:class:LocalAuth), which is also what
an empty mapping means for a local target.
Source code in src/pytruenas/auth.py
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 | |
login(client)
Legacy login via auth.login/login_with_*.
Those methods answer a refusal with False, not an error (measured
on 26.0: a wrong API key or password returned False and left the
session unauthenticated), so False raises
:class:AuthenticationError here.
Source code in src/pytruenas/auth.py
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
login_ex(client, *, login_options=None, otp_provider=None)
Authenticate via the modern auth.login_ex mechanism.
Handles the discriminated response: SUCCESS returns the response
dict; OTP_REQUIRED calls auth.login_ex_continue with an OTP
token (from this credential's own otp if set, else from
otp_provider() if given, else raises); any other response_type
raises :class:AuthenticationError. A credential with no login_ex
mechanism (e.g. :class:LocalAuth) falls back to legacy :meth:login.
login_options overrides the server defaults ({"user_info": True,
"reconnect_token": False}).
Source code in src/pytruenas/auth.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | |
LocalAuth()
Bases: Credentials
Local unix-socket auth: no login call, and no credential to carry.
Source code in src/pytruenas/auth.py
336 337 338 339 340 | |
TokenAuth(token)
Bases: Credentials
Source code in src/pytruenas/auth.py
374 375 | |
MECHANISM = 'TOKEN_PLAIN'
class-attribute
instance-attribute
METHOD = 'login_with_token'
class-attribute
instance-attribute
token = token
instance-attribute
redact_call_args(method, args)
args of an RPC call, safe to log.
auth.* methods take credentials positionally (auth.login(user,
password), login_with_api_key(key)), so their arguments are reduced to
type names. Elsewhere, a dict value under a secret-looking key (password,
*_token, private_key, …) is masked at any depth -- which covers the
SSH private key install_sshcreds uploads.
Source code in src/pytruenas/auth.py
52 53 54 55 56 57 58 59 60 61 62 63 | |