Skip to content

Commit bbf7104

Browse files
committed
Authentication README [ci skip]
1 parent 68f8aee commit bbf7104

File tree

2 files changed

+156
-3
lines changed

2 files changed

+156
-3
lines changed

TODO.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
[X] Add per-service authentication
77
[X] Propagate users from reconfigure server request
88
[X] Add integration tests
9-
[ ] Test manually
9+
[X] Test manually
1010
[X] Update README with env. var. *USERS*
1111
[X] Update README with reconfigure param *users*
1212
[ ] Update README with an article about authentication with the proxy and the listener
13+
[ ] Release Notes
1314

1415
## Videos
1516

articles/swarm-mode-listener.md

+154-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
* [Automatically Reconfiguring the Proxy](#automatically-reconfiguring-the-proxy)
77
* [Removing a Service From the Proxy](#removing-a-service-from-the-proxy)
88
* [Scaling the Proxy](#scaling-the-proxy)
9+
* [Basic Authentication](#basic-authentication)
10+
11+
* [Global Authentication](#global-authentication)
12+
* [Service Authentication](#service-authentication)
13+
914
* [Configuring Service SSLs And Proxying HTTPS Requests](#configuring-service-ssls-and-proxying-https-requests)
1015

1116
* [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
154159

155160
The way the process works is as follows.
156161

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.
158163

159164
Please see the [Reconfigure](../README.md#reconfigure) section for the list of all the arguments that can be used with the proxy.
160165

@@ -259,7 +264,7 @@ If you go back to the command we used to create the `proxy` service, you'll noti
259264
-e LISTENER_ADDRESS=swarm-listener \
260265
```
261266

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.
263268

264269
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.
265270

@@ -295,6 +300,153 @@ One of the important things to note is that, with a system like this, everything
295300

296301
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.
297302

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+
298450
## Configuring Service SSLs And Proxying HTTPS Requests
299451

300452
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

Comments
 (0)