
    cF                        S r SSKJr  SSKJr  SSKJr  SSKrSSK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r\R"                  " S
5      r\R"                  " S5      r\R"                  " S5      r\R"                  " S5      rSr\R"                  " S5      r\R"                  " S5      rS rS rS rS rS rS r " S S\	R>                  5      r S r!S r"S r#S r$S r%S r&g)z1Utility for configuring and parsing secrets args.    )absolute_import)division)unicode_literalsN)arg_parsers)ArgumentTypeError)map_util)logzo^(/+[a-zA-Z0-9-_.]*[a-zA-Z0-9-_]+)+((/*:(/*[a-zA-Z0-9-_.]*[a-zA-Z0-9-_]+)+)|(/+[a-zA-Z0-9-_.]*[a-zA-Z0-9-_]+))$z<^(?P<secret>[a-zA-Z0-9-_]+):(?P<version>[1-9][0-9]*|latest)$zI^projects/([^/]+)/secrets/([a-zA-Z0-9-_]+)/versions/([1-9][0-9]*|latest)$z`^projects/(?P<project>[^/]+)/secrets/(?P<secret>[a-zA-Z0-9-_]+):(?P<version>[1-9][0-9]*|latest)$*ze^(?P<secret_resource>projects/[^/]+/secrets/[a-zA-Z0-9-_]+)/versions/(?P<version>[1-9][0-9]*|latest)$z@^projects/(?P<project>[^/]+)/secrets/(?P<secret>[a-zA-Z0-9-_]+)$c                     [         R                  " SSU 5      n SU ;   a  SOSnU R                  U5      u  p#n[         R                  " SSU5      n[         R                  " SSU5      nSR                  X$5      $ )a7  Canonicalizes secret path to the form `/mount_path:/secret_file_path`.

Gcloud secret path is more restrictive than the backend (shortn/_bwgb3xdRxL).
Paths are reduced to their canonical forms before the request is made.

Args:
  secret_path: Complete path to the secret.

Returns:
  Canonicalized secret path.
z/+/:z/$ z^/z{}:/{})resub
rpartitionformat)secret_path	seperator
mount_path_secret_file_paths        :lib/googlecloudsdk/command_lib/functions/secrets_config.py_CanonicalizePathr   ;   sq     uc;/+K'cS)$/$:$:9$E!*! vveR,*VVE2'78		66    c                 Z   U R                  5       (       d  [        S5      eU n[        R                  U 5      (       a  [	        U 5      nU$ SU ;   a%  [
        R                  " SR                  U 5      5        U R                  S5      (       d  U S;   a  [        SR                  U 5      5      eU$ )zValidates and canonicalizes secrets key configuration.

Args:
  key: Secrets key configuration.

Returns:
  Canonicalized secrets key configuration.

Raises:
  ArgumentTypeError: Secrets key configuration is not valid.
z?Secret environment variable names/secret paths cannot be empty.r   z'{}' will be interpreted as a secret environment variable name as it doesn't match the pattern for a secret path '/mount_path:/secret_file_path'.	X_GOOGLE_)GOOGLE_ENTRYPOINTGOOGLE_FUNCTION_TARGETGOOGLE_RUNTIMEGOOGLE_RUNTIME_VERSIONzCSecret environment variable name '{}' is reserved for internal use.)	stripr   _SECRET_PATH_PATTERNsearchr   r	   warningr   
startswith)keycanonicalized_keys     r   _SecretsKeyTyper(   R   s     

I    %%)#.$ 
! cz	kk--3VC[
 ~~k""c . '   
r   c                    [         R                  U 5      n[        R                  U 5      n[        R                  U 5      nU(       a3  SR	                  [
        UR                  S5      UR                  S5      S9$ U(       a  U $ U(       a>  SR	                  UR                  S5      UR                  S5      UR                  S5      S9$ [        SR	                  U 5      5      e)aR  Canonicalizes secret value reference to the secret version resource name.

Output format: `projects/{project}/secrets/{secret}/versions/{version}`.
The project in the above reference will be * if the user used a default
project secret.

Args:
  value: Secret value reference as a string.

Returns:
  Canonicalized secret value reference.
z6projects/{project}/secrets/{secret}/versions/{version}secretversion)projectr*   r+   r,   zSecrets value configuration must match the pattern 'SECRET:VERSION' or 'projects/{{PROJECT}}/secrets/{{SECRET}}:{{VERSION}}' or 'projects/{{PROJECT}}/secrets/{{SECRET}}/versions/{{VERSION}}' where VERSION is a number or the label 'latest' [{}])#_DEFAULT_PROJECT_SECRET_REF_PATTERNr#   $_SECRET_VERSION_RESOURCE_REF_PATTERN_SECRET_VERSION_REF_PATTERNr   _DEFAULT_PROJECT_IDENTIFIERgroupr   )valuedp_secret_ref_matchsecret_version_res_ref_matchsecret_version_ref_matchs       r   _CanonicalizeValuer6   y   s     <BB5I!E!L!L" 9??FCJJ+"((2#)))4 K  
 $LCJJ(..y9'--h7(..y9 K  
 	= >DVE]		 r   c                 X    SU ;   a  [        SR                  U 5      5      e[        U 5      $ )aV  Validates secrets value configuration.

The restrictions for gcloud are strict when compared to GCF to accommodate
future changes without making it confusing for the user.

Args:
  value: Secrets value configuration.

Returns:
  Secrets value configuration as a string.

Raises:
  ArgumentTypeError: Secrets value configuration is not valid.
=z3Secrets value configuration cannot contain '=' [{}])r   r   r6   )r2   s    r   _SecretsValueTyper9      s3     	E\
=DDUK  
E	""r   c                     X:g  =(       dL    X:g  =(       aA    U R                  5       UR                  5       :H  =(       a    U [        :g  =(       a	    U[        :g  $ )a  Returns true if the two secrets differ.

The secrets can be considered as different if either the secret name is
different or the project is different with the secret name being the same. If
one project is represented using the project number and the other is
represented using its project id, then it may not be possible to determine if
the two projects are the same, so the validation is relaxed.

Args:
  project1: Project ID or number of the first secret.
  secret1: Secret name of the first secret.
  project2: Project ID or number of the second secret.
  secret2: Secret name of the second secret.

Returns:
  True if the two secrets differ, False otherwise.
)isdigitr0   )project1secret1project2secret2s       r   _SecretsDifferr@      sW    $ 
	 
 2



 0 0 2
22
1
12 1
1	r   c           
         [         R                  " [        5      n[        R                  " U 5       GH7  u  p#[
        R                  U5      (       d  M"  UR                  S5      S   n[        R                  U5      R                  S5      nXA;   a  [        R                  U5      nUR                  S5      nUR                  S5      nX    H  n	[        R                  U	5      n
U
R                  S5      nU
R                  S5      n[        XxX5      (       d  MM  [        SR                  UU[        :X  a  UOUU[        :X  a  US95      eU	S95      e   GM$  X   R                  U5        GM:     g)	z|Additional secrets validations that require the entire dict.

Args:
  secrets_dict: Secrets configuration dict to validate.
r   r   secret_resourcer,   r*   znMore than one secret is configured for the mount path '{mount_path}' [violating secrets: {secret1},{secret2}].)r   r=   r?   N)collectionsdefaultdictlistsix	iteritemsr"   r#   split'_SECRET_VERSION_SECRET_RESOURCE_PATTERNr1   _SECRET_RESOURCE_PATTERNr@   r   r   r0   append)secrets_dictmount_path_to_secretr&   r2   r   secret_res1secret_res_match1r<   r=   secret_res2secret_res_match2r>   r?   s                r   _ValidateSecretsrR      s`    %006MM,/jc""3''99S>!$j;BB5IOO
k 
	+4;;KH$**95#))(3/;K6==kJ
&,,Y7(%++H5'HxAA#K)#>> $$#>> $    %    <( 	(//<A 0r   c                   L   ^  \ rS rSrSr        SU 4S jjrU 4S jrSrU =r$ )ArgSecretsDict   z5ArgDict customized for holding secrets configuration.c	                 6   > [         [        U ]  UUUUUUUUS9  g)z:Initializes the base ArgDict by forwarding the parameters.)key_type
value_typespec
min_length
max_lengthallow_key_onlyrequired_keys	operatorsN)superrT   __init__)
selfrW   rX   rY   rZ   r[   r\   r]   r^   	__class__s
            r   r`   ArgSecretsDict.__init__   s1     
.$(%# ) 	r   c           	         > [         R                  " [        [        R                  " [
        [        U ]  U5      5      5      5      n[        U5        U$ )N)	rC   OrderedDictsortedrF   rG   r_   rT   __call__rR   )ra   	arg_valuerL   rb   s      r   rg   ArgSecretsDict.__call__  s@    **s}}U>4A)LMNL \"r    )NNNr   NFNN)	__name__
__module____qualname____firstlineno____doc__r`   rg   __static_attributes____classcell__)rb   s   @r   rT   rT      s/    = . r   rT   c           
         SnSnU R                  5       nUR                  SU[        R                  [	        [
        [        S9SS9  UR                  [        R                  " S5      S9nUR                  S	U[        R                  [	        [
        [        S9S
S9  UR                  SU[        R                  [        R                  " [
        S9SS9  UR                  SSSS9  g)zmAdd flags for configuring secret environment variables and secret volumes.

Args:
  parser: Argument parser.
zlSECRET_ENV_VAR=SECRET_VALUE_REF,/secret_path=SECRET_VALUE_REF,/mount_path:/secret_file_path=SECRET_VALUE_REFz9SECRET_ENV_VAR,/secret_path,/mount_path:/secret_file_path--set-secrets)rW   rX   a)  
      List of secret environment variables and secret volumes to configure.
      Existing secrets configuration will be overwritten.

      You can reference a secret value referred to as `SECRET_VALUE_REF` in the
      help text in the following ways.

      * Use `${SECRET}:${VERSION}` if you are referencing a secret in the same
        project, where `${SECRET}` is the name of the secret in secret manager
        (not the full resource name) and `${VERSION}` is the version of the
        secret which is either a `positive integer` or the label `latest`.
        For example, use `SECRET_FOO:1` to reference version `1` of the secret
        `SECRET_FOO` which exists in the same project as the function.

      * Use `projects/${PROJECT}/secrets/${SECRET}/versions/${VERSION}` or
        `projects/${PROJECT}/secrets/${SECRET}:${VERSION}` to reference a secret
        version using the full resource name, where `${PROJECT}` is either the
        project number (`preferred`) or the project ID of the project which
        contains the secret, `${SECRET}` is the name of the secret in secret
        manager (not the full resource name) and `${VERSION}` is the version of
        the secret which is either a `positive integer` or the label `latest`.
        For example, use `projects/1234567890/secrets/SECRET_FOO/versions/1` or
        `projects/project_id/secrets/SECRET_FOO/versions/1` to reference version
        `1` of the secret `SECRET_FOO` that exists in the project `1234567890`
        or `project_id` respectively.
        This format is useful when the secret exists in a different project.

      To configure the secret as an environment variable, use
      `SECRET_ENV_VAR=SECRET_VALUE_REF`. To use the value of the secret, read
      the environment variable `SECRET_ENV_VAR` as you would normally do in the
      function's programming language.

      We recommend using a `numeric` version for secret environment variables
      as any updates to the secret value are not reflected until new clones
      start.

      To mount the secret within a volume use `/secret_path=SECRET_VALUE_REF` or
      `/mount_path:/secret_file_path=SECRET_VALUE_REF`. To use the value of the
      secret, read the file at `/secret_path` as you would normally do in the
      function's programming language.

      For example, `/etc/secrets/secret_foo=SECRET_FOO:latest` or
      `/etc/secrets:/secret_foo=SECRET_FOO:latest` will make the value of the
      `latest` version of the secret `SECRET_FOO` available in a file
      `secret_foo` under the directory `/etc/secrets`. `/etc/secrets` will be
      considered as the `mount path` and will `not` be available for any other
      volume.

      We recommend referencing the `latest` version when using secret volumes so
      that the secret's value changes are reflected immediately.)metavaractiontypehelpz      Only `--update-secrets` and `--remove-secrets` can be used together. If
      both are specified, then `--remove-secrets` will be applied first.)rw   --update-secretsz
      List of secret environment variables and secret volumes to update.
      Existing secrets configuration not specified in this list will be
      preserved.--remove-secrets)element_typea  
      List of secret environment variable names and secret paths to remove.

      Existing secrets configuration of secret environment variable names and
      secret paths not specified in this list will be preserved.

      To remove a secret environment variable, use the name of the environment
      variable `SECRET_ENV_VAR`.

      To remove a file within a secret volume or the volume itself, use the
      secret path as the key (either `/secret_path` or
      `/mount_path:/secret_file_path`).--clear-secrets
store_truez4Remove all secret environment variables and volumes.)ru   rw   N)add_mutually_exclusive_groupadd_argumentr   UpdateActionrT   r(   r9   add_argument_grouptextwrapdedentArgList)parser
kv_metavar	k_metavar
flag_groupupdate_remove_flag_groups        r   ConfigureFlagsr     s   7 
 J)224*%%"/@1D  9v (::??L ;  ''%%"/@ (  ''%%O<+ ( & A  r   c                 p    1 Skn[        U R                  5       5      n[        UR                  U5      5      $ )zReturns true if at least one of the flags for secrets is specified.

Args:
  args: Argparse namespace.

Returns:
  True if at least one of the flags for secrets is specified.
>   rs   r{   ry   rx   )setGetSpecifiedArgNamesboolintersection)argssecrets_flagsspecified_flagss      r   IsArgsSpecifiedr     s4    - 1134/	o**=9	::r   c                    [         R                  " U 5       VVs0 s H#  u  p[        R                  U5      (       d  M!  X_M%     nnn[         R                  " U 5       VVs0 s H  u  pX;  d  M  X_M     nnn[        R
                  " [        [         R                  " U5      5      5      [        R
                  " [        [         R                  " U5      5      5      4$ s  snnf s  snnf )zSplits the secrets dict into sorted ordered dicts for each secret type.

Args:
  secrets_dict: Secrets configuration dict.

Returns:
  A tuple (secret_env_vars, secret_volumes) of sorted ordered dicts for each
  secret type.
)rF   rG   r"   r#   rC   re   rf   )rL   kvsecret_volumessecret_env_varss        r   SplitSecretsDictr     s     ----$!		$	$Q	' ad-   }}\22tqa6Mdad2   fS]]?%CDEfS]]>%BCD
 
s    CC C$/C$c                 P    [         R                  U 5      (       a  [        U 5      $ U $ )zCanonicalizes secrets configuration key.

Args:
  key: Secrets configuration key.

Returns:
  Canonicalized secrets configuration key.
)r"   r#   r   )r&   s    r   CanonicalizeKeyr     s%       %%S!!	*r   c                 f    [         R                  " SR                  US9SR                  US9U 5      $ )a  Replaces the default project number in place of * or project ID.

Args:
  secret_version_ref: Secret value reference.
  default_project_id: The project ID of the project to which the function is
    deployed.
  default_project_number: The project number of the project to which the
    function is deployed.

Returns:
  Secret value reference with * or project ID replaced by the default project.
zprojects/([*]|{project_id})/)
project_idzprojects/{project_number}/)project_number)r   r   r   )secret_version_refdefault_project_iddefault_project_numbers      r   _SubstituteDefaultProjectr     sB     
%,,8J,K"))/ *  
 r   c           
      T   [         R                  " SU5      n[         R                  " U 40 UD6n[        R                  " U5       VVs0 s H  u  pgU[        XrU5      _M     nnn[        R                  " [        [        R                  " U5      5      5      n[        U5        U$ s  snnf )a3  Applies the current flags to existing secrets configuration.

Args:
  old_secrets: Existing combined secrets configuration dict.
  args: Argparse namespace.
  default_project_id: The project ID of the project to which the function is
    deployed.
  default_project_number: The project number of the project to which the
    function is deployed.

Returns:
  new_secrets: A new combined secrets configuration dict generated by
    applying the flags to the existing secrets configuration.

Raises:
  ArgumentTypeError: Generated secrets configuration is invalid.
secrets)
r   GetMapFlagsFromArgsApplyMapFlagsrF   rG   r   rC   re   rf   rR   )old_secretsr   r   r   secret_flagsnew_secretssecrets_keysecrets_values           r   
ApplyFlagsr     s    $ --i>,&&{ClC+ ),k(B	 )C
$+ ,
-C  )C	   ''s}}[/I(JK+ ;	s   B$)'ro   
__future__r   r   r   rC   r   r   googlecloudsdk.callioper   #googlecloudsdk.calliope.arg_parsersr   $googlecloudsdk.command_lib.util.argsr   googlecloudsdk.corer	   rF   compiler"   r-   r.   r/   r0   rI   rJ   r   r(   r6   r9   r@   rR   ArgDictrT   r   r   r   r   r   r   rj   r   r   <module>r      s   8 &  '  	  / A 9 # 
zz+  ')jjB' # (*zzO( $ !jj( 
 " *,**1+ ' ::F 
7.$N&R#,4'=T[(( Dsl;&00 r   