|
6 | 6 | * [Automatically Reconfiguring the Proxy](#automatically-reconfiguring-the-proxy)
|
7 | 7 | * [Removing a Service From the Proxy](#removing-a-service-from-the-proxy)
|
8 | 8 | * [Scaling the Proxy](#scaling-the-proxy)
|
| 9 | + * [Basic Authentication](#basic-authentication) |
| 10 | + |
| 11 | + * [Global Authentication](#global-authentication) |
| 12 | + * [Service Authentication](#service-authentication) |
| 13 | + |
9 | 14 | * [Configuring Service SSLs And Proxying HTTPS Requests](#configuring-service-ssls-and-proxying-https-requests)
|
10 | 15 |
|
11 | 16 | * [The Flow Explained](#the-flow-explained)
|
@@ -154,7 +159,7 @@ We sent a request to the proxy (the only service listening to the port 80) and g
|
154 | 159 |
|
155 | 160 | The way the process works is as follows.
|
156 | 161 |
|
157 |
| -*Docker Flow: Swarm Listener* is running inside one of the Swarm manager nodes and queries Docker API in search for newly created services. Once it finds a new service, it looks for its labels. If the service contains the `com.df.notify` (it can hold any value), the rest of the labels with keys starting with `com.df.` are retrieved. All those labels are used to form request parameters. Those parameters are appended to the address specified as the `DF_NOTIF_CREATE_SERVICE_URL` environment variable defined in the `swarm-listener` service. Finally, a request is sent. In this particular case, the request was made to reconfigure the proxy with the service `go-demo` (the name of the service), using `/demo` as the path, and running on the port `8080`. The `distribute` label is not necessary in this example since we're running only a single instance of the proxy. However, in production we should run at least two proxy instances (for fault tolerance) and the `distribute` argument means that reconfiguration should be applied to all. |
| 162 | +[Docker Flow: Swarm Listener](https://github.com/vfarcic/docker-flow-swarm-listener) is running inside one of the Swarm manager nodes and queries Docker API in search for newly created services. Once it finds a new service, it looks for its labels. If the service contains the `com.df.notify` (it can hold any value), the rest of the labels with keys starting with `com.df.` are retrieved. All those labels are used to form request parameters. Those parameters are appended to the address specified as the `DF_NOTIF_CREATE_SERVICE_URL` environment variable defined in the `swarm-listener` service. Finally, a request is sent. In this particular case, the request was made to reconfigure the proxy with the service `go-demo` (the name of the service), using `/demo` as the path, and running on the port `8080`. The `distribute` label is not necessary in this example since we're running only a single instance of the proxy. However, in production we should run at least two proxy instances (for fault tolerance) and the `distribute` argument means that reconfiguration should be applied to all. |
158 | 163 |
|
159 | 164 | Please see the [Reconfigure](../README.md#reconfigure) section for the list of all the arguments that can be used with the proxy.
|
160 | 165 |
|
@@ -259,7 +264,7 @@ If you go back to the command we used to create the `proxy` service, you'll noti
|
259 | 264 | -e LISTENER_ADDRESS=swarm-listener \
|
260 | 265 | ```
|
261 | 266 |
|
262 |
| -This tells the proxy the address of the `Docker Flow: Swarm Listener` service. Whenever a new instance of the proxy is created, it will send a request to the listener to resend notifications for all the services. As a result, each proxy instance will soon have the same state as the other. |
| 267 | +This tells the proxy the address of the [Docker Flow: Swarm Listener](https://github.com/vfarcic/docker-flow-swarm-listener) service. Whenever a new instance of the proxy is created, it will send a request to the listener to resend notifications for all the services. As a result, each proxy instance will soon have the same state as the other. |
263 | 268 |
|
264 | 269 | If, for example, an instance of the proxy fails, Swarm will reschedule it and, soon afterwards, a new instance will be created. In that case, the process would be the same as when we scaled the proxy and, as the end result, the rescheduled instance will also have the same state as any other.
|
265 | 270 |
|
@@ -295,6 +300,153 @@ One of the important things to note is that, with a system like this, everything
|
295 | 300 |
|
296 | 301 | A similar logic is used for the destination services. The proxy does not need to do load balancing. Docker networking does that for us. The only thing it needs is the name of the service and that both belong to the same network. As a result, there is no need to reconfigure the proxy every time a new release is made or when a service is scaled.
|
297 | 302 |
|
| 303 | +## Basic Authentication |
| 304 | + |
| 305 | +*Docker Flow: Proxy* can provide basic authentication that can be applied on two levels. We can configure the proxy to protect all or only a selected service. |
| 306 | + |
| 307 | +### Global Authentication |
| 308 | + |
| 309 | +To configure the proxy to protect all the services, we need to specify the environment variable `USERS`. |
| 310 | + |
| 311 | +As an example, we'll update the `proxy` service by adding the environment variable `USERS`. |
| 312 | + |
| 313 | +```bash |
| 314 | +docker service update --env-add "USERS=my-user:my-pass" proxy |
| 315 | +``` |
| 316 | + |
| 317 | +Please wait a few moments until all the instances of the `proxy` are updated. You can monitor the status with the `docker service ps proxy` command. |
| 318 | + |
| 319 | +Let's see what will happen if we send another request to the `go-demo` service. |
| 320 | + |
| 321 | +```bash |
| 322 | +curl -i $(docker-machine ip node-1)/demo/hello |
| 323 | +``` |
| 324 | + |
| 325 | +The output is as follows. |
| 326 | + |
| 327 | +``` |
| 328 | +HTTP/1.0 401 Unauthorized |
| 329 | +Cache-Control: no-cache |
| 330 | +Connection: close |
| 331 | +Content-Type: text/html |
| 332 | +WWW-Authenticate: Basic realm="defaultRealm" |
| 333 | +
|
| 334 | +<html><body><h1>401 Unauthorized</h1> |
| 335 | +You need a valid user and password to access this content. |
| 336 | +</body></html> |
| 337 | +``` |
| 338 | + |
| 339 | +The `proxy` responded with the status `401 Unauthorized`. Our services are not accessible without the username and password. |
| 340 | + |
| 341 | +Let's send one more request but, this time, with the username and password. |
| 342 | + |
| 343 | +```bash |
| 344 | +curl -i -u my-user:my-pass \ |
| 345 | + $(docker-machine ip node-1)/demo/hello |
| 346 | +``` |
| 347 | + |
| 348 | +The response is as follows. |
| 349 | + |
| 350 | +``` |
| 351 | +HTTP/1.1 200 OK |
| 352 | +Date: Sun, 04 Dec 2016 23:37:18 GMT |
| 353 | +Content-Length: 14 |
| 354 | +Content-Type: text/plain; charset=utf-8 |
| 355 | +
|
| 356 | +hello, world! |
| 357 | +``` |
| 358 | + |
| 359 | +Since the request contained the correct username and password, proxy let it through and forwarded it to the `go-demo` service. |
| 360 | + |
| 361 | +Multiple usernames and passwords can be separated with a comma. |
| 362 | + |
| 363 | +```bash |
| 364 | +docker service update \ |
| 365 | + --env-add "USERS=my-user-1:my-pass-1,my-user-2:my-pass-2" \ |
| 366 | + proxy |
| 367 | +``` |
| 368 | + |
| 369 | +Once the update is finished, we will be able to access the services using the user `my-user-1` or `my-user-2`. |
| 370 | + |
| 371 | +```bash |
| 372 | +curl -i -u my-user-2:my-pass-2 \ |
| 373 | + $(docker-machine ip node-1)/demo/hello |
| 374 | +``` |
| 375 | + |
| 376 | +As expected, the proxy responded with the status `200` allowing us to access the service. |
| 377 | + |
| 378 | +Let us remove the global authentication before we proceed further. |
| 379 | + |
| 380 | +```bash |
| 381 | +docker service update \ |
| 382 | + --env-rm "USERS" \ |
| 383 | + proxy |
| 384 | +``` |
| 385 | + |
| 386 | +### Service Authentication |
| 387 | + |
| 388 | +In many cases, we do not want to protect all services but only a selected few. A service can be protected by adding `users` parameter to the `reconfigure` request. Since we are using the [Docker Flow: Swarm Listener](https://github.com/vfarcic/docker-flow-swarm-listener) service to reconfigure the proxy, we'll add the parameter as one more label. |
| 389 | + |
| 390 | +Let's start by removing the `go-demo` service. |
| 391 | + |
| 392 | +```bash |
| 393 | +docker service rm go-demo |
| 394 | +``` |
| 395 | + |
| 396 | +Please wait a few moments until the service is removed and the `swarm-listener` updates the proxy. |
| 397 | + |
| 398 | +Now we can create the `go-demo` service with the label `com.df.users`. |
| 399 | + |
| 400 | +```bash |
| 401 | +docker service create --name go-demo \ |
| 402 | + -e DB=go-demo-db \ |
| 403 | + --network go-demo \ |
| 404 | + --network proxy \ |
| 405 | + --label com.df.notify=true \ |
| 406 | + --label com.df.distribute=true \ |
| 407 | + --label com.df.servicePath=/demo \ |
| 408 | + --label com.df.port=8080 \ |
| 409 | + --label com.df.users=admin:password \ |
| 410 | + vfarcic/go-demo |
| 411 | +``` |
| 412 | + |
| 413 | +We added the `com.df.users` label with the value `admin:password`. Just as with the global authentication, multiple username/password combinations can be separated with comma (`,`). |
| 414 | + |
| 415 | +After a few moments, the `go-demo` service will be created, and `swarm-lister` will update the proxy. |
| 416 | + |
| 417 | +From now on, the `go-demo` service is accessible only if the username and the password are provided. |
| 418 | + |
| 419 | +```bash |
| 420 | +curl -i $(docker-machine ip node-1)/demo/hello |
| 421 | + |
| 422 | +curl -i -u admin:password \ |
| 423 | + $(docker-machine ip node-1)/demo/hello |
| 424 | +``` |
| 425 | + |
| 426 | +The first request should return the status code `401 Unauthorized` while the second went through to the `go-demo` service. |
| 427 | + |
| 428 | +Please note that both *global* and *service* authentication can be combined. In that case, all services would be protected with the users specified through the `proxy` environment variable `USERS` and individual services could overwrite that through the `reconfigure` parameter `users`. |
| 429 | + |
| 430 | +Before we move into the next subject, please remove the service and create it again without authentication. |
| 431 | + |
| 432 | +```bash |
| 433 | +docker service rm go-demo |
| 434 | +``` |
| 435 | + |
| 436 | +Please wait a few moments until the service is removed and the `swarm-listener` updates the proxy. |
| 437 | + |
| 438 | +```bash |
| 439 | +docker service create --name go-demo \ |
| 440 | + -e DB=go-demo-db \ |
| 441 | + --network go-demo \ |
| 442 | + --network proxy \ |
| 443 | + --label com.df.notify=true \ |
| 444 | + --label com.df.distribute=true \ |
| 445 | + --label com.df.servicePath=/demo \ |
| 446 | + --label com.df.port=8080 \ |
| 447 | + vfarcic/go-demo |
| 448 | +``` |
| 449 | + |
298 | 450 | ## Configuring Service SSLs And Proxying HTTPS Requests
|
299 | 451 |
|
300 | 452 | Even though we published the proxy port `443` and it is configured to forward traffic to our services, `SSL` communication still does not work. We can confirm that by sending an HTTPS request to our demo service.
|
|
0 commit comments