
    B                     &   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m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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dlmZ dZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&eejO                  d      z   ejO                  d      z   e jO                  d      z   e!jO                  d      z   dz   Z(ddjS                  e"e#e$e%e&g      z   Z* ee(e*      Z+dd gZ,d!Z- eee"      Z. eee#      Z/ eee$      Z0 ee e%      Z1 ee!e&      Z2d" Z3d# Z4d$ ejj                         z   d%z   d&z   d'z   Z6d$ ejj                         z   d(z   d)z   d*z   d+z   d,z   d-z   d.z   d/z   d0z   Z7d1Z8 ed2      Z9 ed3d4d5e6gd6e9i7      Z: eg d8d6e9i7      Z; ed3d4d9e7gd6e9i7      Z< ed3d4d:e8g ed;       ed<      e9d=7      Z= ed3d4d:e7g ed;       ed>       ed<      e9d?7      Z> ed3d4d@e7g edAdBdC       edD      e9dE7      Z? G dF dGe      Z@yH)Iz
Implementation of HMAC key management command for GCS.

NOTE: Any modification to this file or corresponding HMAC logic
should be submitted in its own PR and release to avoid
concurrency issues in testing.
    )absolute_import)division)print_function)unicode_literals)Command)CommandArgument)ApiSelectorCommandException)CreateHelpText)LogCommandParams)PopulateProjectId)GetCloudApiInstance)GcloudStorageFlag)GcloudStorageMap)InsistAscii)	shim_utilz=
  gsutil hmac create [-p <project>] <service_account_email>
z1
  gsutil hmac delete [-p <project>] <access_id>
z.
  gsutil hmac get [-p <project>] <access_id>
zJ
  gsutil hmac list [-a] [-l] [-p <project>] [-u <service_account_email>]
zR
  gsutil hmac update -s (ACTIVE|INACTIVE) [-e <etag>] [-p <project>] <access_id>
a  
<B>CREATE</B>
  The ``hmac create`` command creates an HMAC key for the specified service
  account:

    gsutil hmac create test.service.account@test_project.iam.gserviceaccount.com

  The secret key material is only available upon creation, so be sure to store
  the returned secret along with the access_id.

<B>CREATE OPTIONS</B>
  The ``create`` sub-command has the following option

  -p <project>                Specify the ID or number of the project in which
                              to create a key.
a  
<B>DELETE</B>
  The ``hmac delete`` command permanently deletes the specified HMAC key:

    gsutil hmac delete GOOG56JBMFZX6PMPTQ62VD2

  Note that keys must be updated to be in the ``INACTIVE`` state before they can be
  deleted.

<B>DELETE OPTIONS</B>
  The ``delete`` sub-command has the following option

  -p <project>                Specify the ID or number of the project from which to
                              delete a key.
a  
<B>GET</B>
  The ``hmac get`` command retrieves the specified HMAC key's metadata:

    gsutil hmac get GOOG56JBMFZX6PMPTQ62VD2

  Note that there is no option to retrieve a key's secret material after it has
  been created.

<B>GET OPTIONS</B>
  The ``get`` sub-command has the following option

  -p <project>                Specify the ID or number of the project from which to
                              get a key.
a  
<B>LIST</B>
  The ``hmac list`` command lists the HMAC key metadata for keys in the
  specified project. If no project is specified in the command, the default
  project is used.

<B>LIST OPTIONS</B>
  The ``list`` sub-command has the following options

  -a                          Show all keys, including recently deleted
                              keys.

  -l                          Use long listing format. Shows each key's full
                              metadata excluding the secret.

  -p <project>                Specify the ID or number of the project from
                              which to list keys.

  -u <service_account_email>  Filter keys for a single service account.
a  
<B>UPDATE</B>
  The ``hmac update`` command sets the state of the specified key:

    gsutil hmac update -s INACTIVE -e M42da= GOOG56JBMFZX6PMPTQ62VD2

  Valid state arguments are ``ACTIVE`` and ``INACTIVE``. To set a key to state
  ``DELETED``, use the ``hmac delete`` command on an ``INACTIVE`` key. If an etag
  is set in the command, it will only succeed if the provided etag matches the etag
  of the stored key.

<B>UPDATE OPTIONS</B>
  The ``update`` sub-command has the following options

  -s <ACTIVE|INACTIVE>        Sets the state of the specified key to either
                              ``ACTIVE`` or ``INACTIVE``.

  -e <etag>                   If provided, the update will only be performed
                              if the specified etag matches the etag of the
                              stored key.

  -p <project>                Specify the ID or number of the project in
                              which to update a key.

z

z
  You can use the ``hmac`` command to interact with service account `HMAC keys
  <https://cloud.google.com/storage/docs/authentication/hmackeys>`_.

  The ``hmac`` command has five sub-commands:
INACTIVEACTIVEz%a, %d %b %Y %H:%M:%S GMTc                 (    t        | d|d|      S )N z= requires an Access ID to be specified as the last argument.
r
   )command_name
subcommandsynopsiss      &platform/gsutil/gslib/commands/hmac.py_AccessIdExceptionr      s    	Z+
, ,    c                    dd}d| j                   z  }| |d| j                        z  }| |d| j                        z  }| |d| j                        z  }| |d| j                  j                  t                    z  }| |d| j                  j                  t                    z  }| |d| j                  d	
      z  }|S )z4Format the key metadata for printing to the console.c                 .    d}d|| dz   |fz  }|r|dz  }|S )z=Format the metadata name-value pair into two aligned columns.   z	%-*s %s:r    )namevaluenew_linewidthinfo_strs        r   
FormatInfoz&_KeyMetadataOutput.<locals>.FormatInfo   s.    EeTCZ77H$hOr   zAccess ID %s:
StatezService AccountProjectzTime CreatedzTime Last UpdatedEtagF)r&   )T)	accessIdstateserviceAccountEmail	projectIdtimeCreatedstrftime_TIME_FORMATupdatedetag)metadatar)   messages      r   _KeyMetadataOutputr8      s      1 11'	Z00'	Z)8+G+GHH'	Z	8#5#566'	Z ,,55lCE E'	Z+ ((11,?A A'	Z>>'	.r   z--format=value[separator="z"](z-format("Access ID:   {}", metadata.accessId),z"format("Secret:      {}", secret))z%"](format("Access ID {}:", accessId),z,format("	State:                 {}", state),z:format("	Service Account:       {}", serviceAccountEmail),z0format("	Project:               {}", projectId),z$format("	Time Created:          {}",z9 timeCreated.date(format="%a',' %d %b %Y %H:%M:%S GMT")),z$format("	Time Last Updated:     {}",z5 updated.date(format="%a',' %d %b %Y %H:%M:%S GMT")),z+format("	Etag:                  {}", etag))zW--format=table[no-heading](format("{}	{:<12} {}",accessId, state, serviceAccountEmail))z	--projectstoragehmaccreate-pgcloud_commandflag_map)r9   r:   deletedescribelistz--allz--service-account)-a-ur<   z--long)rC   -lrD   r<   updatez
--activatez--deactivate)r   r   z--etag)-s-er<   c                       e Zd ZdZ ej
                  ddddddej                  gej                  e e	j                         g e	j                         g e	j                         g e	j                         g e	j                         gd
      Z ej                  dg d	d
eeeeeed      Z fdZddZddZddZddZddZd Z xZS )HmacCommandz&Implementation of gsutil hmac command.r:         z
ae:lp:s:u:Tr;   r@   getrB   rF   )	min_argsmax_argssupported_sub_argsfile_url_okurls_start_arggs_api_supportgs_default_apiusage_synopsisargparse_argumentscommand_helpz-CRUD operations on service account HMAC keys.)	help_namehelp_name_aliases	help_typehelp_one_line_summary	help_textsubcommand_help_textc                     | j                   d   dk(  r"d| j                   v rt        dt        ii       }n't        t        t        t
        t        t        di       }t        | %  |      S )Nr   rB   rE   r=   )r;   r@   rF   rN   rB   )
argsr   LIST_COMMAND_LONG_FORMATCREATE_COMMANDDELETE_COMMANDUPDATE_COMMANDGET_COMMANDLIST_COMMANDsuperget_gcloud_storage_args)selfgcloud_storage_map	__class__s     r   rh   z#HmacCommand.get_gcloud_storage_args<  sn    yy|v$$))"3+ ":;
 ,&&& " 	 7*+=>>r   c                    | j                   r| j                   d   | _        n+d}t        || j                  | j                  t
        fz        t        | |      }|j                  | j                  | j                  d      }t        ddd|j                  j                         t        d	dd|j                         y
)z'Creates HMAC key for a service account.r   zI%s %s requires a service account to be specified as the last argument.
%sthread_stategsproviderz
Access ID:12r   zSecret:N)r`   service_account_emailr   r   action_subcommand_CREATE_SYNOPSISr   CreateHmacKey
project_idprintr6   r-   secret)ri   rn   err_msg
gsutil_apiresponses        r   _CreateHmacKeyzHmacCommand._CreateHmacKeyP  s    yy#'99Q<d &g
d446F
GHI I %TEJ''(,(B(B15 ( 7H 
h&7&7&@&@
AB		8??
34r   c                     | j                   r| j                   d   }n%t        | j                  | j                  t              t        | |      }|j                  | j                  |d       y)zDeletes an HMAC key.r   rm   ro   rp   N)r`   r   r   rt   _DELETE_SYNOPSISr   DeleteHmacKeyrw   )ri   rn   	access_idr{   s       r   _DeleteHmacKeyzHmacCommand._DeleteHmacKeyd  s]    yy))A,it00$2H2H/1 1 %TEJT__i$Gr   c                    | j                   r| j                   d   }n%t        | j                  | j                  t              t        | |      }|j                  | j                  |d      }t        t        |             y)z!Gets HMAC key from its Access Id.r   rm   ro   rp   N)
r`   r   r   rt   _GET_SYNOPSISr   
GetHmacKeyrw   rx   r8   ri   rn   r   r{   r|   s        r   _GetHmacKeyzHmacCommand._GetHmacKeyp  sm    yy))A,it00$2H2H,. . %TEJ$$T__i$$OH	
X
&'r   c                    | j                   r+t        | j                  d| j                  dt              t        | |      }|j                  | j                  | j                  | j                  d      }d}| j                  r&|D ]   }t        t        |             t                " y|D ]1  }t        ||j                  |j                  |j                  fz         3 y)z1Lists HMAC keys for a project or service account.r   z  received unexpected arguments.
rm   ro   rp   z%s	%-12s %sN)r`   r   r   rt   _LIST_SYNOPSISr   ListHmacKeysrw   rs   show_all	long_listrx   r8   r-   r.   r/   )ri   rn   r{   r|   short_list_formatitems         r   _ListHmacKeyszHmacCommand._ListHmacKeys~  s    yyd44nFG G %TEJ&&t'+'A'A'+}}04 ' 6H
 '~~$ &'  $}}djj$*B*BCD 	E r   c                    | j                   s,t        d| j                  d| j                  dt              | j                   t
        vr!t        ddj                  t
              z        | j                  r| j                  d   }n%t        | j                  | j                  t              t        | |      }|j                  | j                  || j                   | j                  d	      }t        t        |             y
)zUpdate an HMAC key's state.z"A state flag must be supplied for r   r   z&The state flag value must be one of %sz, r   rm   ro   rp   N)r.   r   r   rt   _UPDATE_SYNOPSIS_VALID_UPDATE_STATESjoinr`   r   r   UpdateHmacKeyrw   r5   rx   r8   r   s        r   _UpdateHmacKeyzHmacCommand._UpdateHmacKey  s    ::d446FHI I 
/	/E!YY';<= > >yy))A,it00$2H2H/1 1 %TEJ''(1(,

(,		15	 ( 7H 

X
&'r   c                    | j                   j                  d      t        j                  k7  rt	        d      | j
                  j                  d      | _        | j                  d       t        | j                         d| _        d| _        d	| _        d	| _        d| _        | j                  rn| j                  D ]_  \  }}|d
k(  r|| _        |dk(  rt!        |d       || _        ,|dk(  r|| _        9|dk(  rd| _        F|dk(  rd| _        S|dk(  sY|| _        a | j"                  st%        d      | _        | j&                  | j(                  | j*                  | j,                  | j.                  d}| j                  |vr&t	        d| j                  d| j0                  d      t        | j                  g        || j                             y)z)Command entry point for the hmac command.ro   rp   z9The "hmac" command can only be used with the GCS JSON APIr   T)
check_args)sub_optsNFrD   r<   z/Invalid non-ASCII character found in project IDrG   rC   rE   rH   rM   zInvalid subcommand "z
" for the z! command.
See "gsutil help hmac".)subcommands)r{   GetApiSelectorr	   JSONr   r`   poprt   ParseSubOptsr   r   rs   r.   r   r   r5   r   rw   r   r}   r   r   r   r   r   )ri   oamethod_for_args       r   
RunCommandzHmacCommand.RunCommand  s    %%t%48H8HH
EG G "YY]]1-D& dmm,!%DDJDMDNDI}}--$!Q9'($
$$Y
aJ
K$/$Y$*$Y$-$Y$.$Y$)    ??)$/do %%%%""%%N ^3"44d6G6GI J J $"8"8!9:*N4))*,r   )N)__name__
__module____qualname____doc__r   CreateCommandSpecr	   r   	_SYNOPSISr   %MakeZeroOrMoreCloudOrFileURLsArgumentcommand_specHelpSpec_DETAILED_HELP_TEXT_create_help_text_delete_help_text_get_help_text_list_help_text_update_help_text	help_specrh   r}   r   r   r   r   r   __classcell__)rk   s   @r   rJ   rJ     s    .***%!&&' %%J_JJLMJ_JJLMG/GGIJH?HHJKJ_JJLM,& gL#%%!%	)?(5(
H(E0(26r   rJ   N)Ar   
__future__r   r   r   r   gslib.commandr   gslib.command_argumentr   gslib.cs_api_mapr	   gslib.exceptionr   gslib.help_providerr   gslib.metricsr   gslib.project_idr   gslib.utils.cloud_api_helperr   gslib.utils.shim_utilr   r   gslib.utils.text_utilr   gslib.utilsr   ru   r   r   r   r   _CREATE_DESCRIPTION_DELETE_DESCRIPTION_GET_DESCRIPTION_LIST_DESCRIPTION_UPDATE_DESCRIPTIONlstripr   r   _DESCRIPTIONr   r   r3   r   r   r   r   r   r   r8   get_format_flag_newline_CREATE_COMMAND_FORMAT_DESCRIBE_COMMAND_FORMAT_LIST_COMMAND_SHORT_FORMAT_PROJECT_FLAGrb   rc   re   rf   ra   rd   rJ   r#   r   r   <module>r      sZ   '  % ' ! 2 ( , . * . < 3 2 - !    "     ( 2  0 7 7 ==!!$'(*8*?*?*EF$$T*+-34	
 ii  %Y= "H- *"#35HI "#35HI /?@ 1BC"#35HI ,. 7;);;=>@EFIJ ?? 
 !#D9#D#D#FF+,34 BB 8	8
 ,, BB ,, >> 3	3 -  "+.!vx1GHm "1N&*M,$%
 vz3KLM"$  vv/IJ( 34 ,vv/GH() 34	  "vx1IJ &* 
 h'
L' Lr   