
    Ki:%                     V   d Z ddlZddlmc mZ ddlZddlZddl	m
Z
 ddlZej                  j                  d e e
e      j                   j                   j                                ddlmZmZmZ  G d d      Z G d d      Z G d	 d
      Zedk(  r ej2                  edg       yy)u#   utils/redact.py 테스트 스위트    N)Path)RedactingFormatterredact_sensitive_textsetup_redacted_loggingc                       e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zy)TestRedactSensitiveTextu(   redact_sensitive_text() 패턴 테스트c                    d}t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)	u(   일반 텍스트는 변경 없이 통과zhello world==z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   py0py2py4py7assert %(py9)spy9N	r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationself@py_assert1@py_assert3@py_assert6@py_assert5@py_format8@py_format10s          ./home/jay/workspace/utils/tests/test_redact.pytest_passthrough_plain_textz3TestRedactSensitiveText.test_passthrough_plain_text   s    %2D$]3D}D3}DDDD3}DDDDDD$DDD$DDD]DDD3DDD}DDDDDDD    c                    d}t        |      }d}||u }|st        j                  d|fd||f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)u   None 입력은 None 반환N)is)z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} is %(py7)sr   r   r   r   r   r   s          r%   test_none_returns_nonez.TestRedactSensitiveText.test_none_returns_none   s    %)2$T*2d2*d2222*d222222$222$222T222*222d2222222r'   c                    d}t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}}y)	u   빈 문자열 통과 r
   r   r   r   r   r   Nr   r   s          r%   test_empty_stringz)TestRedactSensitiveText.test_empty_string   s    %'.$R(.B.(B....(B......$...$...R...(...B.......r'   c                 f   t        d      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}}y	)
u*   비문자열은 str()로 변환 후 처리*   42r
   )z%(py0)s == %(py3)sresult)r   py3assert %(py5)spy5Nr   )r   r1   @py_assert2r   @py_format4@py_format6s         r%   test_non_string_coercedz/TestRedactSensitiveText.test_non_string_coerced   sd    &r*v~vvvr'   c                    d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u%   sk-로 시작하는 API 키 마스킹%key=sk-abcdefghijklmnopqrstuvwxyz1234!sk-abcdefghijklmnopqrstuvwxyz1234not inz%(py1)s not in %(py3)sr1   py1r2   r3   r4   Nzsk-abcinz%(py1)s in %(py3)s1234	r   r   r   r   r   r   r   r   r   r   textr1   @py_assert0r5   r6   r7   s          r%   test_sk_token_maskedz,TestRedactSensitiveText.test_sk_token_masked$   s   6&t,2@2&@@@@2&@@@2@@@@@@&@@@&@@@@@@@!x6!!!!x6!!!x!!!!!!6!!!6!!!!!!!vvvr'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u"   sk-ant- Anthropic 토큰 마스킹z6ANTHROPIC_API_KEY=sk-ant-api03-verylongkeyhere12345678zapi03-verylongkeyhere12345678r<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_sk_ant_token_maskedz0TestRedactSensitiveText.test_sk_ant_token_masked,   sm    G&t,.<.f<<<<.f<<<.<<<<<<f<<<f<<<<<<<r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u   ghp_ GitHub PAT 마스킹z(token=ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcd"ghp_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdr<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_github_pat_classic_maskedz6TestRedactSensitiveText.test_github_pat_classic_masked3   sm    9&t,3A36AAAA36AAA3AAAAAA6AAA6AAAAAAAr'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u#   github_pat_ 세밀한 PAT 마스킹+github_pat_ABCDEFGHIJKLMNOPQRSTUVWXYZ123456 ABCDEFGHIJKLMNOPQRSTUVWXYZ123456r<   r>   r1   r?   r3   r4   NrE   rF   s          r%   #test_github_pat_fine_grained_maskedz;TestRedactSensitiveText.test_github_pat_fine_grained_masked9   sm    <&t,1?1????1???1????????????????r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u    AKIA AWS Access Key ID 마스킹z&AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLEAKIAIOSFODNN7EXAMPLEr<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_aws_access_key_maskedz2TestRedactSensitiveText.test_aws_access_key_masked@   sm    7&t,%3%V3333%V333%333333V333V3333333r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u   sk_live_ Stripe 키 마스킹z'STRIPE_KEY=sk_live_abcdefghijklmnopqrstsk_live_abcdefghijklmnopqrstr<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_stripe_live_key_maskedz3TestRedactSensitiveText.test_stripe_live_key_maskedG   sm    8&t,-;-V;;;;-V;;;-;;;;;;V;;;V;;;;;;;r'   c                    d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u%   KEY=value 형태 ENV 할당 마스킹z0OPENAI_API_KEY=super_secret_key_value_here_12345!super_secret_key_value_here_12345r<   r>   r1   r?   r3   r4   NzOPENAI_API_KEY=rA   rC   rE   rF   s          r%   test_env_assignment_api_keyz3TestRedactSensitiveText.test_env_assignment_api_keyN   s    A&t,2@2&@@@@2&@@@2@@@@@@&@@@&@@@@@@@ * F**** F*** ******F***F*******r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u1   KEY='value' 따옴표 포함 ENV 할당 마스킹z4DATABASE_PASSWORD='my_very_long_secret_password_xyz' my_very_long_secret_password_xyzr<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_env_assignment_quotedz2TestRedactSensitiveText.test_env_assignment_quotedU   sm    E&t,1?1????1???1????????????????r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u   JSON apiKey 필드 마스킹z*{"apiKey": "supersecretlongvalue12345678"}supersecretlongvalue12345678r<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_json_api_key_fieldz/TestRedactSensitiveText.test_json_api_key_field\   sm    ;&t,-;-V;;;;-V;;;-;;;;;;V;;;V;;;;;;;r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u   JSON token 필드 마스킹z0{"token": "bearer_token_value_very_long_string"}#bearer_token_value_very_long_stringr<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_json_token_fieldz-TestRedactSensitiveText.test_json_token_fieldb   sm    A&t,4B4FBBBB4FBBB4BBBBBBFBBBFBBBBBBBr'   c                    d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u&   Authorization: Bearer 헤더 마스킹z5Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpeyJhbGciOiJSUzI1NiIsInR5cCI6Ikpr<   r>   r1   r?   r3   r4   NzAuthorization: BearerrA   rC   rE   rF   s          r%   test_auth_bearer_headerz/TestRedactSensitiveText.test_auth_bearer_headeri   s    F&t,0>0>>>>0>>>0>>>>>>>>>>>>>>>>&0&&0000&&000&000000&000&0000000r'   c                    d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u   Telegram bot 토큰 마스킹z0bot123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghi#ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghir<   r>   r1   r?   r3   r4   N	123456789rA   rC   rE   rF   s          r%   test_telegram_bot_tokenz/TestRedactSensitiveText.test_telegram_bot_tokenq   s    A&t,4B4FBBBB4FBBB4BBBBBBFBBBFBBBBBBB${f$$$${f$$${$$$$$$f$$$f$$$$$$$r'   c                    d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u'   PEM 형식 Private Key 블록 마스킹zN-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA
-----END RSA PRIVATE KEY-----MIIEpAIBAAKCAQEAr<   r>   r1   r?   r3   r4   Nz[REDACTED PRIVATE KEY]rA   rC   rE   rF   s          r%   test_private_key_blockz.TestRedactSensitiveText.test_private_key_blocky   s    a&t,!/!////!///!////////////////'1'61111'6111'111111611161111111r'   c                    d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)u2   PostgreSQL 연결 문자열 비밀번호 마스킹z4postgresql://user:mysecretpassword@localhost:5432/dbmysecretpasswordr<   r>   r1   r?   r3   r4   Nzpostgresql://user:rA   rC   z
@localhostrE   rF   s          r%   test_postgres_connection_stringz7TestRedactSensitiveText.test_postgres_connection_string   s"   E&t,!/!////!///!////////////////#-#v----#v---#------v---v-------%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%r'   c                 h   d}t        |      }d}||v}|st        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            d	x}}y	)
u-   MySQL 연결 문자열 비밀번호 마스킹z-mysql://admin:p@ssw0rd123@db.example.com/mydbzp@ssw0rd123r<   r>   r1   r?   r3   r4   NrE   rF   s          r%   test_mysql_connection_stringz4TestRedactSensitiveText.test_mysql_connection_string   sj    >&t,*}F****}F***}******F***F*******r'   c                    d}t        |      }g }d}||v }|}|sd}||v}|}|sXt        j                  d|fd||f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }	dd	|	iz  }
|j                  |
       |st        j                  d
fd|f      t        j                  |      dt	        j
                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }|j                  |       t        j                  |d      i z  }dd|iz  }t        t        j                  |            dx}x}x}x}x}}y)u/   18자 미만 토큰은 *** 로 완전 마스킹zAPI_KEY=short_val_xz***short_val_xrA   )z%(py3)s in %(py5)sr1   )r2   r4   z%(py7)sr   r<   )z%(py10)s not in %(py12)s)py10py12z%(py14)spy14   zassert %(py17)spy17N)r   r   r   r   r   r   r   append_format_boolopr   r   )r   rG   r1   r   r5   @py_assert4rH   @py_assert9@py_assert11r7   r#   @py_format13@py_format15@py_format16@py_format18s                  r%   test_short_token_fully_maskedz5TestRedactSensitiveText.test_short_token_fully_masked   s     %&t,=u=u=-=-v"=====u===u================-v===-======v===v==============r'   c                    |j                  dd       d}t        |      }||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  |      rt        j                  |      nddt	        j
                         v st        j                  |      rt        j                  |      nddz  }d	d
|iz  }t        t        j                  |            d}y)u?   DISABLE_REDACT_SECRETS=1 환경변수로 마스킹 비활성화DISABLE_REDACT_SECRETS1r;   r
   )z%(py0)s == %(py2)sr1   rG   )r   r   zassert %(py4)sr   N)
setenvr   r   r   r   r   r   r   r   r   )r   monkeypatchrG   r1   r   @py_format3@py_format5s          r%   test_env_disabled_via_envvarz4TestRedactSensitiveText.test_env_disabled_via_envvar   s    3S92&t,~vvvr'   N)__name__
__module____qualname____doc__r&   r*   r-   r8   rI   rK   rN   rR   rU   rX   r[   r^   ra   rd   rg   rk   rn   rq   rs   r   r    r'   r%   r   r      ss    2E3/ =B@4<+@<C1%2&+>r'   r   c                       e Zd ZdZd Zd Zy)TestRedactingFormatteru-   RedactingFormatter 로그 포맷터 테스트c           	         t        d      }t        j                  dt        j                  ddddd	      }|j	                  |      }d
}||v}|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y)u'   로그 메시지에서 비밀 마스킹%(message)sfmttestr,   r   r:   r   Nnamelevelpathnamelinenomsgargsexc_infor;   r<   r>   outputr?   r3   r4   r   logging	LogRecordINFOformatr   r   r   r   r   r   r   r   r   	formatterrecordr   rH   r5   r6   r7   s           r%   #test_formatter_masks_secrets_in_logz:TestRedactingFormatter.test_formatter_masks_secrets_in_log   s    &=9	"",,7
 !!&)2@2&@@@@2&@@@2@@@@@@&@@@&@@@@@@@r'   c           	         t        d      }t        j                  dt        j                  ddddd	      }|j	                  |      }d}||v }|st        j                  d
|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y)u(   일반 메시지는 변경 없이 통과r   r   r   r,   r   znormal log messager   Nr   rA   rC   r   r?   r3   r4   r   r   s           r%    test_formatter_passes_plain_textz7TestRedactingFormatter.test_formatter_passes_plain_text   s    &=9	"",,$
 !!&)#-#v----#v---#------v---v-------r'   N)r   r   r   r   r   r   r   r'   r%   r   r      s    7A.r'   r   c                   "    e Zd ZdZd Zd Zd Zy)TestSetupRedactedLoggingu)   setup_redacted_logging() 통합 테스트c           	         t        j                  d      }|j                  j                          t        j                         }|j                  t        j                  d             |j                  |       t        |       |j                  D ]E  }|j                  }t        |t              }|sddt        j                         v st        j                  t              rt        j                   t              nddt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      dt        j                         v st        j                  t              rt        j                   t              ndt        j                   |      dz  }t#        t        j$                  |            dx}}H y)	u*   기존 로거에 RedactingFormatter 적용ztest.setup_redactr   Tassert %(py6)s
{%(py6)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.formatter
}, %(py4)s)
}
isinstancehr   r   r@   r2   r   py6N)r   	getLoggerhandlersclearStreamHandlersetFormatter	Formatter
addHandlerr   r   r   r   r   r   r   r   r   r   r   r   loggerhandlerr   r5   r"   @py_format7s          r%   test_applies_to_existing_loggerz8TestSetupRedactedLogging.test_applies_to_existing_logger   s   ""#67'')W..}=>'"v&  	?Akk>:k+=>>>>>>>>:>>>:>>>>>>a>>>a>>>k>>>>>>+=>>>+=>>>>>>>>>>	?r'   c           	         t        j                         }t        |j                        }t        j                         }|j                  t        j                  d             |j                  |       	 t                |j                  D ]E  }|j                  }t        |t              }|sddt        j                         v st        j                  t              rt        j                   t              nddt        j                         v st        j                  |      rt        j                   |      ndt        j                   |      dt        j                         v st        j                  t              rt        j                   t              ndt        j                   |      dz  }t#        t        j$                  |            dx}}H 	 |j'                  |       t        |j                        D ]  }||vs|j'                  |        y# |j'                  |       t        |j                        D ]  }||vs|j'                  |        w xY w)u0   인수 없이 호출 시 루트 로거에 적용r   r   r   r   r   r   N)r   r   listr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   removeHandler)r   rootoriginal_handlerstest_handlerr   r5   r"   r   s           r%   &test_applies_to_root_logger_by_defaultz?TestSetupRedactedLogging.test_applies_to_root_logger_by_default   s     " / ,,.!!'"3"3M"BC%
	*"$]] C"#++Bz+/ABBBBBBBBzBBBzBBBBBB!BBB!BBB+BBBBBB/ABBB/ABBBBBBBBBBC |,$--( *--&&q)* |,$--( *--&&q)*s   4EH .IIc           	      l   t        j                  d      }|j                  j                          t        j                         }|j                  |       t        |       |j                  D ]E  }|j                  }t        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                   |            dx}}H y)u5   formatter가 없는 핸들러도 오류 없이 처리ztest.no_formatterr   r   r   r   r   N)r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s          r%   *test_no_error_on_handler_without_formatterzCTestSetupRedactedLogging.test_no_error_on_handler_without_formatter   s    ""#67'')'" 	v& 	?Akk>:k+=>>>>>>>>:>>>:>>>>>>a>>>a>>>k>>>>>>+=>>>+=>>>>>>>>>>	?r'   N)r   r   r   r   r   r   r   r   r'   r%   r   r      s    3?*,?r'   r   __main__z-v)r   builtinsr   _pytest.assertion.rewrite	assertionrewriter   r   syspathlibr   pytestpathinsertstr__file__parentutils.redactr   r   r   r   r   r   r   mainr   r'   r%   <module>r      s    )    
   3tH~,,33::; < Z ZO Od. .D4? 4?n zFKK4 ! r'   