Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1611d78

Browse files
nejchJohnVillalovos
authored andcommitted
feat(client): mask tokens by default when logging
1 parent2a2404f commit1611d78

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

‎docs/api-usage.rst‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,27 @@ user. For example:
406406
407407
p= gl.projects.create({'name':'awesome_project'},sudo='user1')
408408
409+
Logging
410+
=======
411+
412+
To enable debug logging from the underlying ``requests`` and ``http.client`` calls,
413+
you can use ``enable_debug()`` on your ``Gitlab`` instance. For example:
414+
415+
..code-block::python
416+
417+
import os
418+
import gitlab
419+
420+
gl= gitlab.Gitlab(private_token=os.getenv("GITLAB_TOKEN"))
421+
gl.enable_debug()
422+
423+
By default, python-gitlab will mask the token used for authentication in logging output.
424+
If you'd like to debug credentials sent to the API, you can disable masking explicitly:
425+
426+
..code-block::python
427+
428+
gl.enable_debug(mask_credentials=False)
429+
409430
.. _object_attributes:
410431

411432
Attributes in updated objects

‎gitlab/client.py‎

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -517,18 +517,39 @@ def _set_auth_info(self) -> None:
517517
self.http_username,self.http_password
518518
)
519519

520-
@staticmethod
521-
defenable_debug()->None:
520+
defenable_debug(self,mask_credentials:bool=True)->None:
522521
importlogging
523-
fromhttp.clientimportHTTPConnection# noqa
522+
fromhttpimportclient
524523

525-
HTTPConnection.debuglevel=1
524+
client.HTTPConnection.debuglevel=1
526525
logging.basicConfig()
527-
logging.getLogger().setLevel(logging.DEBUG)
526+
logger=logging.getLogger()
527+
logger.setLevel(logging.DEBUG)
528+
529+
httpclient_log=logging.getLogger("http.client")
530+
httpclient_log.propagate=True
531+
httpclient_log.setLevel(logging.DEBUG)
532+
528533
requests_log=logging.getLogger("requests.packages.urllib3")
529534
requests_log.setLevel(logging.DEBUG)
530535
requests_log.propagate=True
531536

537+
# shadow http.client prints to log()
538+
# https://stackoverflow.com/a/16337639
539+
defprint_as_log(*args:Any)->None:
540+
httpclient_log.log(logging.DEBUG," ".join(args))
541+
542+
setattr(client,"print",print_as_log)
543+
544+
ifnotmask_credentials:
545+
return
546+
547+
token=self.private_tokenorself.oauth_tokenorself.job_token
548+
handler=logging.StreamHandler()
549+
handler.setFormatter(utils.MaskingFormatter(masked=token))
550+
logger.handlers.clear()
551+
logger.addHandler(handler)
552+
532553
def_get_session_opts(self)->Dict[str,Any]:
533554
return {
534555
"headers":self.headers.copy(),

‎gitlab/utils.py‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
importemail.message
2+
importlogging
23
importpathlib
34
importtraceback
45
importurllib.parse
56
importwarnings
6-
fromtypingimportAny,Callable,Dict,Iterator,Optional,Tuple,Type,Union
7+
fromtypingimportAny,Callable,Dict,Iterator,Literal,Optional,Tuple,Type,Union
78

89
importrequests
910

@@ -22,6 +23,31 @@ def get_content_type(content_type: Optional[str]) -> str:
2223
returnmessage.get_content_type()
2324

2425

26+
classMaskingFormatter(logging.Formatter):
27+
"""A logging formatter that can mask credentials"""
28+
29+
def__init__(
30+
self,
31+
fmt:Optional[str]=logging.BASIC_FORMAT,
32+
datefmt:Optional[str]=None,
33+
style:Literal["%","{","$"]="%",
34+
validate:bool=True,
35+
masked:Optional[str]=None,
36+
)->None:
37+
super().__init__(fmt,datefmt,style,validate)
38+
self.masked=masked
39+
40+
def_filter(self,entry:str)->str:
41+
ifnotself.masked:
42+
returnentry
43+
44+
returnentry.replace(self.masked,"[MASKED]")
45+
46+
defformat(self,record:logging.LogRecord)->str:
47+
original=logging.Formatter.format(self,record)
48+
returnself._filter(original)
49+
50+
2551
defresponse_content(
2652
response:requests.Response,
2753
streamed:bool,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp