github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/docs/source/sysadmin_guide/rest_auth_proxy.rst (about)

     1  **********************************************
     2  Using a Proxy Server to Authorize the REST API
     3  **********************************************
     4  
     5  As a lightweight shim on top of internal communications, requests sent to the
     6  *Hyperledger Sawtooth* REST API are simply passed on to the validator, without
     7  any sort of authorization. While this is in keeping with the public nature of
     8  blockchains, that behavior may not be desirable in every use case. Rather than
     9  internally implementing one authorization scheme or another, the REST API is
    10  designed to work well behind a proxy server, allowing any available
    11  authorization scheme to be implemented externally.
    12  
    13  
    14  Forwarding URL Info with Headers
    15  ================================
    16  
    17  For the most part putting the REST API behind a proxy server should just work.
    18  The majority of what it does will work equally well whether or not it is
    19  communicating directly with a client. The notable exceptions being the `"link"`
    20  parameter sent back in the response envelope, and the `"previous"` and `"next"`
    21  links that are sent back with a paging response. These URLs can be a
    22  convenience for clients, but not when crucial URL information is destroyed by
    23  proxying. In that case, a link that should look like this:
    24  
    25  .. code-block:: json
    26  
    27     {
    28       "link": "https://hyperledger.org/sawtooth/blocks?head=..."
    29     }
    30  
    31  Might instead look like this:
    32  
    33  .. code-block:: json
    34  
    35     {
    36       "link": "http://localhost:8008/blocks?head=..."
    37     }
    38  
    39  The solution to this problem is sending the destroyed information using HTTP
    40  request headers. The Sawtooth REST API will properly recognize and parse two
    41  sorts of headers.
    42  
    43  
    44  "X-Forwarded" Headers
    45  ---------------------
    46  
    47  Although they aren't part of any standard, the various *X-Forwarded* headers
    48  are a very common way of communicating useful information about a proxy. There
    49  are three of these headers that the REST API may look for when building links.
    50  
    51  .. list-table::
    52     :widths: 20, 44, 16
    53     :header-rows: 1
    54  
    55     * - header
    56       - description
    57       - example
    58     * - **X-Forwarded-Host**
    59       - The domain name of the proxy server.
    60       - *hyperledger.org*
    61     * - **X-Forwarded-Proto**
    62       - The protocol/scheme used to make request.
    63       - *https*
    64     * - **X-Forwarded-Path**
    65       - An uncommon header implemented specially by the REST API to handle extra
    66         path information. Only necessary if the proxy endpoints do not map
    67         directly to the REST API endpoints (i.e.
    68         *"hyperledger.org/sawtooth/blocks"* -> *"localhost:8008/blocks"*).
    69       - */sawtooth*
    70  
    71  
    72  "Forwarded" Header
    73  ------------------
    74  
    75  Although less common, the same information can be sent using a single
    76  *Forwarded* header, standardized by
    77  `RFC7239 <https://tools.ietf.org/html/rfc7239#section-4>`_. The Forwarded
    78  header contains semi-colon-separated key value pairs. It might for example look
    79  like this:
    80  
    81  .. code-block:: text
    82  
    83     Forwarded: for=196.168.1.1; host=proxy1.com, host=proxy2.com; proto="https"
    84  
    85  There are three keys in particular the REST API will look for when building
    86  response links:
    87  
    88  .. list-table::
    89     :widths: 8, 52, 20
    90     :header-rows: 1
    91  
    92     * - key
    93       - description
    94       - example
    95     * - **host**
    96       - The domain name of the proxy server.
    97       - *host=hyperledger.org*
    98     * - **proto**
    99       - The protocol/scheme used to make request.
   100       - *proto=https*
   101     * - **path**
   102       - An non-standard key header used to handle extra path information. Only
   103         necessary if the proxy endpoints do not map directly to the REST API
   104         endpoints (i.e. *"hyperledger.org/sawtooth/blocks"* ->
   105         *"localhost:8008/blocks"*).
   106       - *path="/sawtooth"*
   107  
   108  .. note::
   109  
   110     Any key in a *Forwarded* header can be set multiple times, each instance
   111     comma-separated, allowing for a chain of proxy information to be traced.
   112     However, the REST API will always reference the leftmost of any particular
   113     key. It is only interested in producing an accurate link for the original
   114     client.
   115  
   116  
   117  Apache Proxy Setup Guide
   118  ========================
   119  
   120  For further clarification, this section walks through the setup of a simple
   121  `Apache 2 <https://httpd.apache.org/>`_ proxy server secured with Basic Auth
   122  and https, pointed at an instance of the *Sawtooth* REST API.
   123  
   124  
   125  Install Apache
   126  --------------
   127  
   128  We'll begin by installing Apache and its components. These commands may require
   129  ``sudo``.
   130  
   131  .. code-block:: console
   132  
   133     $ apt-get update
   134     $ apt-get install -y apache2
   135     $ a2enmod ssl
   136     $ a2enmod headers
   137     $ a2enmod proxy_http
   138  
   139  
   140  Set Up Passwords and Certificates
   141  ---------------------------------
   142  
   143  First we'll create a password file for the user *"sawtooth"*, with the password
   144  *"sawtooth"*. You can
   145  `generate other .htpasswd files <http://www.htaccesstools.com/htpasswd-generator/>`_
   146  as well, just make sure to authorize those users in the config file below.
   147  
   148  .. code-block:: console
   149  
   150     $ echo "sawtooth:\$apr1\$cyAIkitu\$Cv6M2hHJlNgnVvKbUdlFr." >/tmp/.password
   151  
   152  Then we'll use ``openssl`` to build a self-signed SSL certificate. This
   153  certificate will not be good enough for most HTTP clients, but is suitable for
   154  testing purposes.
   155  
   156  .. code-block:: console
   157  
   158     $ openssl req -x509 -nodes -days 7300 -newkey rsa:2048 \
   159         -subj /C=US/ST=MN/L=Mpls/O=Sawtooth/CN=sawtooth \
   160         -keyout /tmp/.ssl.key \
   161         -out /tmp/.ssl.crt
   162  
   163  
   164  Configure Proxy
   165  ---------------
   166  
   167  Now we'll set up the proxy by editing an Apache config files. This may require
   168  ``sudo``.
   169  
   170  .. code-block:: console
   171  
   172     $ vi /etc/apache2/sites-enabled/000-default.conf
   173  
   174  Edit the file to look like this:
   175  
   176  .. code-block:: apache
   177  
   178     <VirtualHost *:443>
   179         ServerName sawtooth
   180         ServerAdmin sawtooth@sawtooth
   181         DocumentRoot /var/www/html
   182  
   183         SSLEngine on
   184         SSLCertificateFile /tmp/.ssl.crt
   185         SSLCertificateKeyFile /tmp/.ssl.key
   186         RequestHeader set X-Forwarded-Proto "https"
   187  
   188         <Location />
   189             Options Indexes FollowSymLinks
   190             AllowOverride None
   191             AuthType Basic
   192             AuthName "Enter password"
   193             AuthUserFile "/tmp/.password"
   194             Require user sawtooth
   195             Require all denied
   196         </Location>
   197     </VirtualHost>
   198  
   199     ProxyPass /sawtooth http://localhost:8008
   200     ProxyPassReverse /sawtooth http://localhost:8008
   201     RequestHeader set X-Forwarded-Path "/sawtooth"
   202  
   203  .. note::
   204  
   205     Apache will automatically set the *X-Forwarded-Host* header.
   206  
   207  
   208  Start Apache, a Validator, and the REST API
   209  -------------------------------------------
   210  
   211  Start or restart Apache as appropriate. This may require ``sudo``.
   212  
   213  .. code-block:: console
   214  
   215     $ apachectl start
   216  
   217  .. code-block:: console
   218  
   219     $ apachectl restart
   220  
   221  
   222  Start a validator, and the REST API.
   223  
   224  .. code-block:: console
   225  
   226     $ sawadm keygen
   227     $ sawadm genesis
   228     $ sawtooth-validator -v --endpoint localhost:8800
   229     $ sawtooth-rest-api -v
   230  
   231  
   232  Send Test Requests
   233  ------------------
   234  
   235  Finally, let's use ``curl`` to make some requests and make sure everything
   236  worked. We'll start by querying the REST API directly:
   237  
   238  .. code-block:: console
   239  
   240     $ curl http://localhost:8008/blocks
   241  
   242  The response link should look like this:
   243  
   244  .. code-block:: json
   245  
   246     {
   247       "link": "http://localhost:8008/blocks?head=..."
   248     }
   249  
   250  You should also be able to get back a ``401`` by querying the proxy without
   251  authorization:
   252  
   253  .. code-block:: console
   254  
   255     $ curl https://localhost/sawtooth/blocks --insecure
   256  
   257  .. note::
   258  
   259     The ``--insecure`` flag just forces curl to complete the request even though
   260     there isn't an official SSL Certificate. It does *not* bypass Basic Auth.
   261  
   262  And finally, if we send a properly authorized request:
   263  
   264  .. code-block:: console
   265  
   266     $ curl https://localhost/sawtooth/blocks --insecure -u sawtooth:sawtooth
   267  
   268  We should get back a response that looks very similar to querying the REST API
   269  directly, but with a new *link* that reflects the URL we sent the request to:
   270  
   271  .. code-block:: json
   272  
   273     {
   274       "link": "https://localhost/sawtooth/blocks?head=..."
   275     }
   276  
   277  .. Licensed under Creative Commons Attribution 4.0 International License
   278  .. https://creativecommons.org/licenses/by/4.0/