
    h9                         d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlZddlmZ ddl	m
Z
 dd	lmZ dd
lmZ ddlm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)z9Shared utility functions for Cloud SCC findings commands.    )absolute_import)division)print_function)unicode_literalsN)encoding)securitycenter_client)errors)util)timesc                     d| j                   v r8| j                  d      s| j                  d      rt        j                  d      yy)IValidates that only a full resource name or split arguments are provided./organizationsourcezOnly provide a full resource name (organizations/123/sources/456/findings/789) or an --organization flag and --sources flag, not both.N)findingIsKnownAndSpecifiedr	   InvalidSCCInputErrorargss    3lib/googlecloudsdk/command_lib/scc/findings/util.py.ValidateMutexOnFindingAndSourceAndOrganizationr      sL    DLL
~.		!	!(	+

%
%	)  
,     c                    t        j                  d      }t        j                  d      }t        j                  d      }|j                  | j                        r| j                  S |j                  | j                        r|dk(  rt	        | |      S | j                  S |j                  | j                        rt        | |       d| j                   S t        j                  d      )a>  Returns relative resource name for a finding name.

  Args:
    args: Argument namespace.
    version: Api version.

  Returns:
    Relative resource name
    if no location is specified the result will be one of the following forms
      `organizations/{organization_id}/sources/{source_id}/finding/{finding_id}`
      `folders/{folders_id}/sources/{source_id}/finding/{finding_id}`
      `projects/{projects_id}/sources/{source_id}/finding/{finding_id}`
    if a location is specified the result will be one of the following forms
      `organizations/{organization_id}/sources/{source_id}/locations/{location_id}/finding/{finding_id}`
      `folders/{folders_id}/sources/{source_id}/locations/{location_id}/finding/{finding_id}`
      `projects/{projects_id}/sources/{source_id}/locations/{location_id}/finding/{finding_id}`
  J(organizations|projects|folders)/.*/sources/[0-9-]+/findings/[a-zA-Z0-9]+$W(organizations|projects|folders)/.*/sources/[0-9-]+/locations/.*/findings/[a-zA-Z0-9]+$z^[a-zA-Z0-9]+$v2z
/findings/zHFinding must match either the full resource name or only the finding id.)recompilematchr   GetRegionalizedResourceNameGetFullSourceNamer	   r   )r   versionresource_patternregion_resource_pattern
id_patterns        r   GetFullFindingNamer&   ,   s    $ ZZR JJ_ zz*+*""4<<0<<DLL)$(w77<<dll#g./z$,,HH##P	 r   c                 4   t        j                  d      }t        j                  d      }t        j                  d      }| j                  st        j                  d      |j                  | j                        r| j                  S t        j                  | |      }|j                  | j                        r| j                  }|dk(  r| d| S |S |j                  | j                        rJt        | d      st        | d      r2t        j                  |        d	| j                   }|dk(  r| d| S |S |j                  | j                        r2t        j                  |        d	| j                   }|dk(  r| d| S |S t        j                  d
      )az  Returns relative resource name for a source from --source argument.

  Args:
    args: Argument namespace.
    version: Api version.

  Returns:
    Relative resource name
    if args.source is not provided an exception will be raised
    if no location is specified in argument: sources/{source_id}
    if a location is specified: sources/{source_id}/locations/{location_id}
  z3(organizations|projects|folders)/.*/sources/[0-9-]+zL(organizations|projects|folders)/.*/sources/[0-9-]+/locations/[a-zA-Z0-9-]+$z[0-9-]+zGFinding source must be provided in --source flag or full resource name.r   /locations/r   parentz	/sources/zJThe source must either be the full resource name or the numeric source ID.)r   r   r   r	   r   r   scc_utilValidateAndGetLocationhasattr(GetFindingsParentFromPositionalArguments GetParentFromPositionalArguments)r   r"   r#   r$   r%   locationr   s          r   r!   r!   T   s    ZZ; JJT zz)$*	

%
%	 
 ""4;;/;;,,T7;(DKK([[F$x{8*--Mt{{#tY74#:AA$GH	RVR]R]Q^_F$x{8*--Mdkk"99$?@	$++WF$x{8*--M##'	 r   c           
      ,   t        j                  d      }|j                  |       st        j                  d      | j                  d      }|dk(  rt        |        d|d    d|d    S |dk(  r%t        |        d|d    d|d    d|d    d|d	    	S y
)a;  Get parent (with source) from Finding name i.e remove 'findings/{finding_name}'.

  Args:
    resource_name: finding name {parent with source}/findings/{findingID}
    version: API version.

  Returns:
    The parent with source or parent with source and location
    examples:
    if no location is specified the result will be one of the following forms
      `organizations/{organization_id}/sources/{source_id}`
      `folders/{folders_id}/sources/{source_id}`
      `projects/{projects_id}/sources/{source_id}`
    if a location is specified the result will be one of the following forms
      `organizations/{organization_id}/sources/{source_id}/locations/{location_id}`
      `folders/{folders_id}/sources/{source_id}/locations/{location_id}`
      `projects/{projects_id}/sources/{source_id}/locations/{location_id}`
  z2(organizations|projects|folders)/.*/sources/[0-9]+zfWhen providing a full resource path, it must also include the organization, project, or folder prefix.r   v1      r         N)r   r   r   r	   r   splitGetParentFromResourceName)resource_namer"   r#   list_source_componentss       r   GetSourceParentFromFindingNamer:      s   & ZZ: 
			.

%
%	7  )..s3_'67q9OPQ9R8SSTUklmUnTopp_'67q9OPQ9R8SSTUklmUnToop  rH  IJ  rK  qL  LM  Nd  ef  Ng  Mh  i  i r   c                    t        j                  d      }t        j                  d      }|j                  |       s&|j                  |       st        j                  d      | j                  d      }|t        |      dz
     S )z.Gets a finding id from the full resource name.r   r   z|When providing a full resource path, it must include the pattern organizations/[0-9]+/sources/[0-9-]+/findings/[a-zA-Z0-9]+.r      )r   r   r   r	   r   r6   len)finding_namer#   r$   list_finding_componentss       r   GetFindingIdFromNamer@      s    ZZR JJ_ 
		
#)),7

%
%	F  )..s3	 %<!=!A	BBr   c                 >    | j                  d      }|d    d|d    S )Nr   r   r<   )r6   )r8   list_organization_componentss     r   r7   r7      s1    !.!4!4S!9(+,A.J1.M-N	OOr   c                 *   t        j                  |      }| r| j                         } i }|dk(  rf|j                  j                  j
                  }|j                  j                  j                  |j                  j                  j                  |d|d<   ne|j                  j                  j
                  }|j                  j                  j                  |j                  j                  j                  |d|d<   ||   j                  | ||   d         S )zDConvert state input to messages.Finding.StateValueValuesEnum object.r1   )ACTIVEINACTIVESTATE_UNSPECIFIEDr   rF   )
r   GetMessagesupperFindingStateValueValuesEnumrF   rD   rE   "GoogleCloudSecuritycenterV2Findingget)stater"   messages
state_dictunspecified_statev2_unspecified_states         r   ConvertStateInputrR      s    "..w7(
KKME*_ ((==OO""77>>$$99BB.Jt 	33HHZZ 
 77LLSS 77LLUU1Jt 
G		 	 Z !45
 r   c                     | dk(  r |j                   j                  j                  S | dk(  r |j                   j                  j                  S t	        j
                  d      )z]Convert mute state input to messages.BulkMuteFindingsRequest.MuteStateValueValuesEnum object.muted	undefinedz-Mute state must be one of [muted, undefined].)BulkMuteFindingsRequestMuteStateValueValuesEnumMUTED	UNDEFINEDr	   r   )
mute_staterN   s     r   ConvertMuteStateInputr[      sX    7++DDJJJ[ ++DDNNN##5	 r   c                 j   | j                   d| j                   v rQt        j                  d      }|j                  | j                         st	        j
                  d      | j                   S t        j                  d      }|j                  | j                         st	        j
                  d      d| j                    S | j                  nd| j                  v rQt        j                  d      }|j                  | j                        st	        j
                  d	      | j                  S d
| j                   S | j                  nd| j                  v rQt        j                  d      }|j                  | j                        st	        j
                  d      | j                  S d| j                   S y)zValidates parent.Nr   z^organizations/[0-9]{1,19}$z_When providing a full resource path, it must include the pattern '^organizations/[0-9]{1,19}$'.z^[0-9]{1,19}$z8Organization does not match the pattern '^[0-9]{1,19}$'.zorganizations/z^folders/.*$zPWhen providing a full resource path, it must include the pattern '^folders/.*$'.zfolders/z^projects/.*$zQWhen providing a full resource path, it must include the pattern '^projects/.*$'.z	projects/)r   r   r   r   r	   r   folderproject)r   patterns     r   ValidateAndGetParentr`      s   	"
d

89g]]4,,-))-
 	

    

?+g]]4,,-))F
 	
   1 1233	[[
dkk

>*g]]4;;'))
 	

 {{}%%	\\
dll

?+g]]4<<())
 	

 ||'' r   c                 d    d| j                   v r"| j                  t        j                  d      yy)r   r   Nz_Only provide a full resource name (organizations/123/sources/456) or a --parent flag, not both.)r   r)   r	   r   r   s    r   ValidateMutexOnSourceAndParentrb   $  s8    DKKDKK3

%
%	H  4r   c                     ~t        | t              r| }nt        |       }t        |      dkD  rt        j                  d      |D ]  }|j
                  j                  c S  y)z-Returns security marks from finding response.r<   zVListFindingResponse must only return one finding since it is filtered by Finding Name.N)
isinstancelistr=   r	   r   r   securityMarks)responser   list_finding_responsefinding_results       r    ExtractSecurityMarksFromResponserj   -  sc    
$$ N	!#

%
%	$  .n!!/// .r   c                     | j                   t        j                  d      d| j                  v rt        j                  d      y)zHValidates that source and finding id are provided if parent is provided.Nz--source flag must be provided.r   z?Finding id must be provided, instead of the full resource name.)r   r	   r   r   r   s    r   *ValidateSourceAndFindingIdIfParentProvidedrl   =  sE    	[[

%
%&G
HHDLL

%
%I  r   c                    | j                   rud| j                   v rVt        j                  d      }|j                  | j                         st	        j
                  d      | d| j                    S | d| j                    S y)zAppends location to parent.r   z^locations/[A-Za-z0-9-]{0,61}$zRWhen providing a full resource path, it must include the pattern '^locations/.*$'.r(   N)r/   r   r   r   r	   r   )r   r)   r_   s      r   (ValidateLocationAndGetRegionalizedParentrn   G  s}    	]]
dmm

;<g]]4==))) 
 	

 4==/**x{4==/22 r   c                     t        j                  | |      }| j                  j                  d      }|d    d|d    d|d    d|d    d| d|d    d|d    S )	z#Returns regionalized resource name.r   r   r<   r2   r3   r(   r4   r5   )r*   r+   r   r6   )r   r"   r/   name_componentss       r   r    r    W  s    ,,T7;(LL&&s+/Aq!3 4Aoa6H5I?[\K]J^^ijrisst  vE  FG  vH  uI  IJ  KZ  [\  K]  J^  
_  _r   c                    t        j                  |      }|dk(  r*t        j                  | |j                  j
                        S |dk(  r*t        j                  | |j                  j
                        S t        j                  d      )zAHook to capture "key1=val1,key2=val2" as SourceProperties object.r1   r   zInvalid API version)	r   rG   r   DictToMessagerI   SourcePropertiesValuerK   r	   InvalidAPIVersion)source_properties_dictr"   rN   s      r   ConvertSourcePropertiesrv   ^  s    "..w7(_!! 0 0 F F  $!!33II  	  !677r   c                     | j                   st        j                  |       }n| j                   }t        j                  | ||      S )zADetermine what version to call from --location and --api-version.)r)   r*   r.   GetVersionFromArguments)r   deprecated_argsr)   s      r    GetApiVersionUsingDeprecatedArgsrz   m  s9    	 66t<F[[F		)	)$	HHr   c                     	 t        j                  |       }t        j                  |      S # t         j                  t         j                  f$ r}t        j                  d      |d}~ww xY w)zValidates the export time.z[Invalid export time format. Please provide a valid date/time. Example: 2024-08-20T12:00:00ZN)r   ParseDateTimeFormatDateTimeDateTimeSyntaxErrorDateTimeValueErrorr	   r   )export_timeread_time_dtes      r   ValidateAndFormatExportTimer   x  sf    &&{3L--

#
#U%=%=	> 

%
%	  s   ), #A*A%%A*c                 |    t        j                  d      }|j                  |       st        j                  d      | S )zValidates the dataset.z/^projects/[a-zA-Z0-9-]+/datasets/[a-zA-Z0-9_]+$zMDataset must match the pattern projects/[a-zA-Z0-9-]+/datasets/[a-zA-Z0-9_]+.)r   r   r   r	   r   )datasetdataset_patterns     r   ValidateDatasetr     sB    JJ7/ 
		w	'

%
%	:  
.r   )#__doc__
__future__r   r   r   r   r   apitools.base.pyr   googlecloudsdk.api_lib.sccr   googlecloudsdk.command_lib.sccr	   r
   r*   googlecloudsdk.core.utilr   r   r&   r!   r:   r@   r7   rR   r[   r`   rb   rj   rl   rn   r    rv   rz   r   r    r   r   <module>r      s    @ &  % ' 	 % < 1 ; *
%P7t iFC&P
@-(`0 3 _8I	
r   