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/