
    #E                        S r SSKJr  SSKJr  SSKJr  SSKJr  SSKrSSKJ	r	  SSKJ
r
  SS	KJr  SS
KJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSK J!r"  SSK#J$r$  SSK#J%r%  SSK&J'r'  SSK(r(SSK)J*r*  SSK+r( " S S\RX                  5      r- " S S\-5      r. " S S\-5      r/ " S S \-5      r0S! r1S" r2S# r3 " S$ S%\	Rh                  5      r5S& r6S' r7S( r8S) r9S* r:S+ r;\Rx                  " 5       4S, jr=S- r>S. r?S/\Rx                  " 5       4S0 jr@S1 rAS2 rBS3 rCS4 rDS5 rES6 rF\S9S7 j5       rGS:S8 jrHg);z,Utilities for the container images commands.    )absolute_import)division)unicode_literals)contextmanagerN)docker_creds)docker_name)docker_http)docker_image)docker_image_list)container_analysis_data_util)filter_util)requests)apis)
exceptions)log)	resources)
transports)store)	constants)docker)times)mapc                       \ rS rSrSrSrg)	UtilError4   zBase class for util errors. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       3lib/googlecloudsdk/api_lib/container/images/util.pyr   r   4   s    #r$   r   c                       \ rS rSrSrSrg)InvalidImageNameError8   z4Raised when the user supplies an invalid image name.r   Nr   r   r$   r%   r'   r'   8   s    <r$   r'   c                       \ rS rSrSrSrg)UserRecoverableV2Error<   z;Raised when a user-recoverable V2 API error is encountered.r   Nr   r   r$   r%   r*   r*   <   s    Cr$   r*   c                       \ rS rSrSrSrg)TokenRefreshError@   z/Raised when there's an error refreshing tokens.r   Nr   r   r$   r%   r-   r-   @   s    7r$   r-   c                 $    SU ;   =(       d    SU ;   $ )N:@r   )
image_names    r%   IsFullySpecifiedr3   D   s    	
		/cZ//r$   c                     SnSnSn[         R                  " U5      n[         R                  " U5      n[         R                  " U5      nUR                  U 5      S L =(       a-    UR                  U 5      S L =(       a    UR                  U 5      S L $ )Nz^([a-z0-9-]*)-docker.pkg.devzdocker.([a-z0-9-]*).rep.pkg.devz^([a-z0-9-]*)[.]?gcr.io)recompilematch)registry
ar_patternar_rep_patterngcr_patternar_progar_rep_proggcr_progs          r%   IsInvalidRegistryr?   H   s    -*4.)+JJz"'

>*+ZZ$(nnX$& .
--
!T
).


H
%
-r$   c                    [        U 5      (       a  [        S5      eU R                  S5      (       a  [        S5      e U [        R                  ;   a  [
        R                  " U 5      nO[
        R                  " U 5      n[        UR                  5      (       a  [        R                  " U 5      eU$ ! [
        R                   a$  n[        [        R                  " U5      5      eSnAff = f)aE  Validates the repository path.

Args:
  repository_path: str, The repository path supplied by a user.

Returns:
  The parsed docker_name.Repository object.

Raises:
  InvalidImageNameError: If the image name is invalid.
  docker.UnsupportedRegistryError: If the path is valid, but belongs to a
    registry we don't support.
zPImage names must not be fully-qualified. Remove the tag or digest and try again./zFImage name cannot end with '/'. Remove the trailing '/' and try again.N)r3   r'   endswithr   MIRROR_REGISTRIESr   Registry
Repositoryr?   r8   r   UnsupportedRegistryErrorBadNameExceptionsix	text_type)repository_path
repositoryes      r%   ValidateRepositoryPathrM   V   s     o&&
	  c""
 !K L L
2)555''8j))/:j,,--++O<<		%	% 2
a 0
112s   A2B1 1C)C$$C)c                   @   ^  \ rS rSrSrSrU 4S jr\S 5       rSr	U =r
$ )CredentialProvidery   zFCredentialProvider is a class to refresh oauth2 creds during requests._tokenc                 B   > [         [        U ]  U R                  S5        g )Nzdoes not matter)superrO   __init__	_USERNAME)self	__class__s    r%   rT   CredentialProvider.__init__~   s    	
d,T^^=NOr$   c                 ,    [         R                  " 5       $ N)c_storeGetAccessTokenIfEnabled)rV   s    r%   passwordCredentialProvider.password   s    **,,r$   r   )r   r   r    r!   r"   rU   rT   propertyr]   r#   __classcell__)rW   s   @r%   rO   rO   y   s%    N)P - -r$   rO   c                     [        U 5      n[        US-  5      n [        R                  " U5      $ ! [        [        R
                  4 a     g f = f)Ni  )floatroundr   GetDateTimeFromTimeStampArithmeticErrorDateTimeValueError)time_created_ms	timestamps     r%   _TimeCreatedToDateTimeri      sN    O$)I$%))))44
533	4 s   1 AAc                 d   U R                   [        R                  ;   a  [        R                  $ U R                   [        R                  ;   a  [        R
                  $ U R                  R                  S5      nSUS   ;  a  US   $ [        U5      S:  a  US   S-   US   -   $ [        SUS   5      e)z.Recovers the project-id from a GCR repository.rA   .r      r0   z*Domain-scoped app missing project name: %s)
r8   r   rC   MIRROR_PROJECTLAUNCHER_REGISTRIESLAUNCHER_PROJECTrK   splitlen
ValueError)rK   partss     r%   RecoverProjectIdrt      s    I777###I999%%%



%
%c
*%a8O
5zA~8c>E!H$$
A58
LLr$   c                 H    SR                  [        R                  " U 5      S9$ )Nzhttps://{repo}@repoformatrH   rI   rv   s    r%   _UnqualifiedResourceUrlrz      s    		!	!s}}T':	!	;;r$   c                 J    SR                  [        R                  " U 5      US9$ )Nzhttps://{repo}@{digest}rw   digestrx   r|   s     r%   _ResourceUrlr~      s(    	"	)	)==v 
* 
/ /r$   c                      SR                  U S9$ )Nzhttps://{digest}r}   )ry   r   s    r%   _FullyqualifiedDigestr      s    		"	"&	"	11r$   c                    [         R                  " SS5      n[         R                  " SS5      n[        R                  R                  U SS9nUR                  UR                  5       US9nUR                  R                  U5      $ )z(Helper function to make Summary request.containeranalysisv1alpha1zcloudresourcemanager.projects)
collection)parentfilter)
r   GetClientInstanceGetMessagesModuler   REGISTRYParseBContaineranalysisProjectsOccurrencesGetVulnerabilitySummaryRequestRelativeNameprojects_occurrencesGetVulnerabilitySummary)
project_id
url_filterclientmessagesproject_refreqs         r%   _MakeSummaryRequestr      s    !!"5zB&##$7D(""((< ) >+ HH))+J I @  
	$	$	<	<S	AAr$   c                 J   [         R                  " U 5      n[        U 5      n[        R                  " X1R                  5       5      nU H  nUR                  U5        M     SUR                  ;   a  UR                  S/5      R                  / 5      n[        R                  " X6R                  5       5      n[        R                  " U 5      nU HB  nUR                  (       d  M  XR                  R                  ;   d  M1  UR                  U5        MD     UR                  5         U$ )z;Transforms the occurrence data from Container Analysis API.
DEPLOYMENT)r   ContainerAndAnalysisDatart   r   ListOccurrences	GetFilter
add_recordkinds	WithKindsWithResourcesrH   rI   
deploymentresourceUriresolveSummaries)	r2   occurrence_filteranalysis_objr   occsocc
dep_filterdep_occsimage_strings	            r%   TransformContainerAnalysisDatar      s     .FF,
+*		!	!*.I.I.K	L$cC   &,,,",,l^<JJ
J''
4H4H4JKH==,L^^	33	3$	  !	r$   c                 b    [        U 5      nSR                  US9n[        R                  " X#5      $ )zFetches the summary of vulnerability occurrences for some resource.

Args:
  repository: A parsed docker_name.Repository object.
  resource_url: The URL identifying the resource.

Returns:
  A GetVulnzOccurrencesSummaryResponse.
zresource_url = "{resource_url}")resource_url)rt   ry   r   r   )rK   r   r   r   s       r%   FetchSummaryr      s7      
+*077 8 !*		)	)*	AAr$   c                     [        U 5      n0 n[        R                  " X!R                  5       5      nU H>  nUR                  U;  a  / X5R                  '   X5R                     R                  U5        M@     U$ )z:Fetches the occurrences attached to the list of manifests.)rt   r   ListOccurrencesWithFiltersGetChunkifiedFiltersr   append)rK   r   r   occurrences_by_resourcesoccurrencesr   s         r%   FetchOccurrencesr      so    
+*3388:<+c
6624/__-44S9  
"!r$   Fc                    U (       d  / $ 0 nU(       a	  [        XS9n/ n[        R                  " U 5       GH1  u  pgUUR                  S/ 5      [	        UR                  S5      5      S.nUR                  [        X5      / 5       H>  n	U	R                  U;  a  / XR                  '   XR                     R                  U	5        M@     U(       a  UR                  (       aw  0 US'   [        X5      n
XR                  ;  a  M  [        X5      nUR                   H;  nUR                  (       d  M  UR                  US   [        UR                  5      '   M=     UR                  U5        GM4     U$ )z2Transforms the manifests returned from the server.)r   tagtimeCreatedMs)r}   tagsrh   vuln_counts)r   rH   	iteritemsgetri   r~   kindr   r   r   countsseverity
totalCountstr)	manifestsrK   show_occurrencesr   r   resultskvresultr   r   summaryseverity_counts                r%   TransformManifestsr      sA   
 
I +"9K 'mmI&daeR +AEE/,BCF |J:B?		xxXXc" @
 -77 f] "*0l	88	8Z6g#NN."""'' 
N$;$; <
= +
 NN69 ': 
.r$   c                    U R                   S-   U R                  -   n[        U5      n[        R                  " [        5       UUS9 nU R                  UR                  5       ;  a  / sSSS5        $ UR                  5       R                  U R                  0 5      nUR                  S/ 5      sSSS5        $ ! , (       d  f       g= f)Gets all of the tags for a given digest.

Args:
  digest: docker_name.Digest, The digest supplied by a user.
  http_obj: http.Http(), The http transport.

Returns:
  A list of all of the tags associated with the input digest.
rA   basic_credsname	transportNr   )	r8   rK   rM   
v2_2_imageFromRegistryrO   r}   r   r   )r}   http_objrJ   rK   imagemanifest_values         r%   GetTagNamesForDigestr   "  s     OOc)F,=,==/%o6*$&Z"}}EOO--	 
 __&**6=="=NeR(  s    B50;B55
Cc                 z   U R                   S-   U R                  -   n[        U5      n/ n[        X5      nU HE  n [        R
                  " [        R                  " U5      S-   U-   5      nUR                  U5        MG     U$ ! [        R                   a$  n[        [        R                  " U5      5      eSnAff = f)r   rA   r0   N)r8   rK   rM   r   r   TagrH   rI   rG   r'   r   )	r}   r   rJ   rK   r   	tag_namestag_namer   rL   s	            r%   GetDockerTagsForDigestr   7  s     OOc)F,=,==/%o6*	$"64)h4OOCMM*5;hFGc 	KK  
+ '' 4!#--"2334s   0BB:B55B:c                 <    SU R                   ;  a  [        S5      eU $ )NrA   z=Image name should start with *.gcr.io/project_id/image_path. )rK   r'   )digest_or_tags    r%   ValidateImagePathAndReturnr   N  s+    (((
 !C D D	r$   c                 h   [        U 5      (       d  U S-  n  [        [        R                  " U 5      5      $ ! [        R                   a     Of = fU R                  SS5      n[        U5      S:X  aq  US   R                  S5      (       d  [        SR                  U 5      5      e[        US   5      S:  a,  [        U 5      nX :X  a  [        SR                  U 5      5      eUn  [        [        R                  " U 5      5      $ ! [        R                   a    [        SR                  U 5      5      ef = f)	aL  Gets an image object given either a tag or a digest.

Args:
  image_name: Either a fully qualified tag or a fully qualified digest.
    Defaults to latest if no tag specified.

Returns:
  Either a docker_name.Tag or a docker_name.Digest object.

Raises:
  InvalidImageNameError: Given digest could not be resolved to a full digest.
z:latestr1   rl      zsha256:z3[{0}] digest must be of the form "sha256:<digest>".G   z-[{0}] could not be resolved to a full digest.)r3   r   r   r   rG   rp   rq   
startswithr'   ry   GetDockerDigestFromPrefixDigest)r2   rs   resolveds      r%   GetDockerImageFromTagOrDigestr   V  s.    
*	%	%)J	%kooj&ABB		%	% 		 

3
"%Z1_8y))!
?
F
F  58}v*:6h		#;BB:NP 	Pj%k&8&8&DEE		%	% 
=DD	 s   6 AA#D /D1c                    [        U 5      nS nS nS nU" U5      =(       d    U" U5      =(       d    U" U5      nU(       d  [        SR                  U 5      5      e[        U[        R
                  5      (       d  [        R                  " S5        [        R
                  " SR                  UR                  UR                  US95      $ )zGets a digest object given a repository, tag or digest.

Args:
  image_name: A docker image reference, possibly underqualified.

Returns:
  a docker_name.Digest object.

Raises:
  InvalidImageNameError: If no digest can be resolved.
c                     [         R                  " [        5       U [        5       S9 nUR	                  5       (       a  UR                  5       sS S S 5        $  S S S 5        g ! , (       d  f       g = fNr   )v2_imager   rO   Httpexistsr}   )r   v2_imgs     r%   ResolveV2Tag'GetDigestFromName.<locals>.ResolveV2Tag  sS    			&(s&
#	}}	
 

 
 
 
   %A A  
A.c                     [         R                  " [        5       U [        5       [        R
                  S9 nUR                  5       (       a  UR                  5       sS S S 5        $  S S S 5        g ! , (       d  f       g = f)N)r   r   r   accepted_mimes)r   r   rO   r   v2_2_docker_httpSUPPORTED_MANIFEST_MIMESr   r}   )r   v2_2_imgs     r%   ResolveV22Tag(GetDigestFromName.<locals>.ResolveV22Tag  sj    		 	 &(&'@@	
B FN			 
B 
B 
B 
B 
Bs   %A/%A//
A=c                     [         R                  " [        5       U [        5       S9 nUR	                  5       (       a  UR                  5       sS S S 5        $  S S S 5        g ! , (       d  f       g = fr   )r   r   rO   r   r   r}   )r   manifest_lists     r%   ResolveManifestListTag1GetDigestFromName.<locals>.ResolveManifestListTag  sZ    		'	'&(s&
*					##%	
 

 
 
 
r   z[{0}] is not found or is not a valid name. Expected tag in the form "base:tag" or "tag" or digest in the form "sha256:<digest>"zRSuccessfully resolved tag to sha256, but it is recommended to use sha256 directly.z {registry}/{repository}@{sha256})r8   rK   sha256)
r   r'   ry   
isinstancer   r   r   warningr8   rK   )r2   tag_or_digestr   r   r   r   s         r%   GetDigestFromNamer     s     0
;- ]+ "}]/K "=! 	 

	Fz  
M;#5#5	6	6KK ' ( 
		>EE%%)) F  
 r$   c                 (   U R                  SS5      u  p[        U5      n[        R                  " [	        5       U[        5       S9 nUR                  5        Vs/ s H  oUR                  U5      (       d  M  UPM     nn[        U5      S:X  a  US-   UR                  5       -   sSSS5        $ [        U5      S:  a8  [        SR                  USR                  [        [        U5      5      5      5      eU sSSS5        $ s  snf ! , (       d  f       g= f)zGets a full digest string given a potential prefix.

Args:
  digest: The digest prefix

Returns:
  The full digest, or the same prefix if no full digest is found.

Raises:
  InvalidImageNameError: if the prefix supplied isn't unique.
r1   rl   r   Nz4{0} is not a unique digest prefix. Options are {1}.]z, )rp   rM   r   r   rO   r   r   r   rq   popr'   ry   joinr   r   )r}   rJ   prefixrK   r   dmatchess          r%   r   r     s     #LLa0/%o6*$&Z //+D+Q||F/Cq+GD
7|qs"W[[]2  
W	!
@
G
GdiiC 1245 5   E s+   DC>6C><&D,AD>D
Dc              #     #     S v   g ! [         R                  [        R                  4 a  nUR                  [        R
                  R                  R                  [        R
                  R                  R                  4;   a7  [        SR                  U =(       d    [        R                  " U5      5      5      eUR                  [        R
                  R                  R                  :X  a7  [        SR                  U =(       d    [        R                  " U5      5      5      ee S nAf[         R                  [        R                  4 a$  n[        [        R                  " U5      5      eS nAff = f7f)NzAccess denied: {}zNot found: {})v2_docker_httpV2DiagnosticExceptionr   statusrH   moveshttp_clientUNAUTHORIZED	FORBIDDENr*   ry   rI   	NOT_FOUNDTokenRefreshExceptionr-   )optional_image_nameerrs     r%   WrapExpectedDockerlessErrorsr    s    0	

.
.

0
0
2 


zz		**CII,A,A,K,K  ##6#=#=

3s!3$5 6 6	syy,,66	6"?#9#9

3s!3$5 6 6	

.
.

0
0
2 0
CMM#.
//0s1   E2	 E2$E/C7D$$'E/E**E//E2c                 *    [         R                  " U S9$ )a  Gets an transport client for use with containerregistry.

For now, this just calls into GetApitoolsTransport, but if we find that
implementation does not satisfy our needs, we may need to fork it. This
small amount of indirection will make that change a bit cleaner.

Args:
  timeout: the http timeout in seconds

Returns:
  1. A httplib2.Http-like object backed by httplib2 or requests.
timeout)r   GetApitoolsTransportr  s    r%   r   r     s     
	(	(	99r$   rZ   )unset)Ir"   
__future__r   r   r   
contextlibr   r5   containerregistry.clientr   r   containerregistry.client.v2r	   r  r
   r   containerregistry.client.v2_2r   r   r   'googlecloudsdk.api_lib.container.imagesr   (googlecloudsdk.api_lib.containeranalysisr   r   googlecloudsdk.api_lib.utilr   googlecloudsdk.corer   r   r   r   googlecloudsdk.core.credentialsr   r[   googlecloudsdk.core.dockerr   r   googlecloudsdk.core.utilr   rH   	six.movesr   six.moves.http_clientErrorr   r'   r*   r-   r3   r?   rM   BasicrO   ri   rt   rz   r~   r   r   ContainerAnalysisFilterr   r   r   r   r   r   r   r   r   r   r  r   r   r$   r%   <module>r)     sF   3 &  ' % 	 1 0
 F @ I D ; P @ = , * # ) * < 0 - * 
  $
   $=I =DY D8	 80 2F
-++ 
-	M</
2B #."E"E"G2B 
" ).)4)L)L)N-`)*.*Z?D8 0 0&:r$   