Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic Authentication credentials not respected in Docker Swarm mode #2171

Closed
austinfrey opened this issue Sep 24, 2017 · 23 comments

Comments

@austinfrey
Copy link

commented Sep 24, 2017

Do you want to request a feature or report a bug?

What did you do?

What did you expect to see?

When using traefik.frontend.auth.basic=user:password as a label in my docker-compose.yml i expect to be able to hit my API endpoint with curl -u user:password http://localhost

I'm using docker stacks to deploy

What did you see instead?

401 unauthorized

Output of traefik version: (What version of Traefik are you using?)

Docker image traefik:v1.3

Version:      v1.3.8
Codename:     raclette
Go version:   go1.8.3
Built:        2017-09-07_08:46:19PM
OS/Arch:      linux/amd64

What is your environment & configuration (arguments, toml, provider, platform, ...)?

version: "3.2"                                                                                                                      
services:                                                                                                                           
    traefik:                                                                                                                        
        image: traefik:v1.3                                                                                                         
        command: -c --docker=true                                                                                                   
           --docker.swarmmode=true                                                                                                  
           --docker.domain=traefik                                                                                                  
           --docker.watch=true                                                                                                      
           --web=true                                                                                                               
           --debug=true                                                                                                             
           --defaultEntryPoints='http'                                                                                              
           --entryPoints='Name:http Address::80'                                                                                    
        ports:                                                                                                                      
            - 80:80                                                                                                                 
            - 8080:8080                                                                                                             
        volumes:                                                                                                                    
            - "/var/run/docker.sock:/var/run/docker.sock"                                                                           
        networks:                                                                                                                   
            - functions                                                                                                             
        deploy:                                                                                                                     
            placement:                                                                                                              
                constraints: [node.role == manager]                                                                                 
                                                                                                                                    
    gateway:                                                                                                                        
        volumes:                                                                                                                    
            - "/var/run/docker.sock:/var/run/docker.sock"                                                                           
        image: functions/gateway:0.6.3                                                                                              
        networks:                                                                                                                   
            - functions                                                                                                             
        environment:                                                                                                                
            dnsrr: "true"  # Temporarily use dnsrr in place of VIP while issue persists on PWD                                      
        deploy:                                                                                                                     
            labels:                                                                                                                 
                - traefik.port=8080                                                                                                 
                - traefik.frontend.rule=PathPrefix:/function                                                                        
                - traefik.frontend.auth.basic=user:password                                                                         
            placement:                                                                                                              
                constraints:                                                                                                        
                    - 'node.role == manager'    
                    - 'node.platform.os == linux'                                                                                   

If applicable, please paste the log output in debug mode (--debug switch)

func_traefik.1.oqcqbrh7zivo@desktop    | time="2017-09-24T21:46:13Z" level=debug msg="Validation of load balancer method for backend backend-func-gateway failed: invalid load-balancing method ''. Using default method wrr." 
func_traefik.1.oqcqbrh7zivo@desktop    | time="2017-09-24T21:46:13Z" level=debug msg="Configuration received from provider docker: {"backends":{"backend-func-gateway":{"servers":{"server-func_gateway-1":{"url":"http://10.0.0.30:8080","weight":0}},"loadBalancer":{"method":"wrr"}}},"frontends":{"frontend-PathPrefix-function":{"entryPoints":["http"],"backend":"backend-func-gateway","routes":{"route-frontend-PathPrefix-function":{"rule":"PathPrefix:/function"}},"passHostHeader":true,"priority":0,"basicAuth":["user:password"]}}}" 
func_traefik.1.oqcqbrh7zivo@desktop    | time="2017-09-24T21:46:13Z" level=info msg="Skipping same configuration for provider docker" ```
@nmengin

This comment has been minimized.

Copy link
Member

commented Sep 25, 2017

Hello @austinfrey

Your Træfik configuration seems to check if your URL contains the PathPrefix:/function to redirect you to your backend with basic auth.

Did you try the command described below too?

curl -u user:password http://localhost/function

@austinfrey

This comment has been minimized.

Copy link
Author

commented Sep 25, 2017

@nmengin apologies, that is the command I used. Edited my original post

@nmengin

This comment has been minimized.

Copy link
Member

commented Sep 25, 2017

@austinfrey

I tried to use your configuration and, apparently, you forget few " in the labels part :

            labels:                                                                                                                 
                - "traefik.port=8080"                                                           
                - "traefik.frontend.rule=PathPrefix:/function"                                                                    
                - "traefik.frontend.auth.basic=user:password"

Moreover, I had to add your domain name (docker.domain=traefik) in my /etc/hosts file. Did you do it?

@austinfrey

This comment has been minimized.

Copy link
Author

commented Sep 25, 2017

@nmengin it doesn't seem to matter if those lines are quoted or not, the labels are correctly added either way, and the basic auth seems to be functioning, just credentials are not respected. Also, if I remove the basic.auth label i can hit my endpoint, not problem, so would I need to add that line to my /etc/hosts file?
did it work for you?

@nmengin

This comment has been minimized.

Copy link
Member

commented Sep 25, 2017

@austinfrey

I had to replace the = by a : in the basic label as described below :

- "traefik.frontend.auth.basic:test:$$apr1$$AcSItQWn$$RzSzRH2m.aTQghvg9c04C."

And now it works fine.

Can you try this solution?

@austinfrey

This comment has been minimized.

Copy link
Author

commented Sep 25, 2017

@nmengin the above line creates a label that looks like this

"traefik.frontend.auth.basic:test:$apr1$AcSItQWn$RzSzRH2m.aTQghvg9c04C.": "",

which is not recognized as a legitimate label

@ldez

This comment has been minimized.

Copy link
Member

commented Sep 25, 2017

@austinfrey like that:

            labels:                                                                                                                 
                - "traefik.port=8080"                                                           
                - "traefik.frontend.rule=PathPrefix:/function"                                                                    
                - "traefik.frontend.auth.basic:test:$$apr1$$AcSItQWn$$RzSzRH2m.aTQghvg9c04C."
@austinfrey

This comment has been minimized.

Copy link
Author

commented Sep 25, 2017

@ldez @nmengin the above is exactly what i used, and it applied this label and still doesn't work

"traefik.frontend.auth.basic:test:$apr1$AcSItQWn$RzSzRH2m.aTQghvg9c04C.": "",

Thanks for the help so far

@ldez ldez changed the title Basic Authentication credentials not respected in Docker Swarm Basic Authentication credentials not respected in Docker Swarm mode Sep 25, 2017

@Berndinox

This comment has been minimized.

Copy link

commented Sep 26, 2017

Did work for me without any issues:

version: '3'

services:
  cadvisor:
    image: google/cadvisor
    deploy:
      labels:
        - "traefik.port=8080"
        - "traefik.docker.network=proxy"
        - "traefik.frontend.rule=Host:metrics.mysite.at"
        - "traefik.backend=cadvisor"
        - "traefik.frontend.entryPoints=http,https"
        - "traefik.frontend.auth.basic=berndinox:$$some$$Secret$$passwd$$md5$$escape"
      replicas: 1
    networks:
      proxy:
        aliases:
          - cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
@nmengin

This comment has been minimized.

Copy link
Member

commented Sep 26, 2017

@austinfrey

In the solution we suggest with @ldez , the label key is traefik.frontend.auth.basic and its value is test:$apr1$AcSItQWn$RzSzRH2m.aTQghvg9c04C..
We just replaced the separator = by :.

But your label seems to use traefik.frontend.auth.basic:test:$apr1$AcSItQWn$RzSzRH2m.aTQghvg9c04C. as the key with an empty value.

Am I wrong?

@Berndinox Can you show your Træfik configuration?

@Berndinox

This comment has been minimized.

Copy link

commented Sep 26, 2017

traefik.toml

logLevel = "INFO"
debug = false
defaultEntryPoints = ["http", "https"]

[entryPoints]
 [entryPoints.http]
 address = ":80"
 compress = false
   [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      CertFile = "/etc/traefik/cert.at.cert"
      KeyFile = "/etc/traefik/key.at.key"


[docker]
domain = "docker.localhost"
watch = true
swarmmode = true
version: "3"

services:
  traefik:
    image: traefik
    #command: --consul --consul.endpoint=consul:8500
    #command: storeconfig --consul --consul.endpoint=consul:8500
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
      #- 8080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - traefikdata:/etc/traefik/
    deploy:
      replicas: 3
      #replicas: 1
      placement:
        constraints: [node.role == manager]
      update_config:
        parallelism: 1
        delay: 45s
        monitor: 15s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 10
        window: 60s

volumes:
  traefikdata:
    driver: local-persist
    driver_opts:
      mountpoint: /data/docker/proxy

networks:
  proxy:
    external: true
@austinfrey

This comment has been minimized.

Copy link
Author

commented Sep 26, 2017

version: "3.2"                                                                                                                      
services:                                                                                                                           
    traefik:                                                                                                                        
        image: traefik:v1.3                                                                                                         
        command: -c --docker=true                                                                                                   
           --docker.swarmmode=true                                                                                                  
           --docker.domain=traefik                                                                                                  
           --docker.watch=true                                                                                                      
           --web=true                                                                                                               
           --debug=true                                                                                                             
           --defaultEntryPoints='http'                                                                                              
           --entryPoints='Name:http Address::80'                                                                                    
        ports:                                                                                                                      
            - 80:80                                                                                                                 
            - 8080:8080                                                                                                             
        volumes:                                                                                                                    
            - "/var/run/docker.sock:/var/run/docker.sock"                                                                           
        networks:                                                                                                                   
            - functions                                                                                                             
        deploy:                                                                                                                     
            placement:                                                                                                              
                constraints: [node.role == manager]                                                                                 
                                                                                                                                    
    gateway:                                                                                                                        
        volumes:                                                                                                                    
            - "/var/run/docker.sock:/var/run/docker.sock"                                                                           
        image: functions/gateway:0.6.3                                                                                              
        networks:                                                                                                                   
            - functions                                                                                                             
        environment:                                                                                                                
            dnsrr: "true"  # Temporarily use dnsrr in place of VIP while issue persists on PWD                                      
        deploy:                                                                                                                     
            labels:                                                                                                                 
                - traefik.port=8080                                                                                                 
                - traefik.frontend.rule=PathPrefix:/function                                                                        
                - traefik.frontend.auth.basic=user:password                                                                         
            placement:                                                                                                              
                constraints:                                                                                                        
                    - 'node.role == manager'    
                    - 'node.platform.os == linux' 

I've tried the above and the suggested - traefik.frontend.authbasic:user:password I've also tried quoted and unquoted. Does not work for me yet :( I'm going to try the toml file example above. Thanks again for the feedback all.

@austinfrey

This comment has been minimized.

Copy link
Author

commented Sep 27, 2017

I wasn't using the MD5 hash value in the label, :face_palm: apologies everyone. Closing, hopefully there will be enough closed issues to bury my shame!

Thanks again to everyone who chimed in.

@austinfrey austinfrey closed this Sep 27, 2017

@ldaume

This comment has been minimized.

Copy link

commented Oct 19, 2017

Sorry, but I still have the same issue.

Traefik runs in swarm mode with:

docker service create \
    --name traefik \
    --constraint=node.role==manager \
    -p 80:80 -p 8080:8080 \
    --mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
    --mount type=bind,source=/etc/traefik/traefik.toml,destination=/etc/traefik/traefik.toml \
    --mode global \
    --network traefik-net \
    --label traefik.frontend.passHostHeader=true \
    traefik:1.4  traefik

The traefik.toml file:

logLevel = "INFO"

[accessLog]

[web]
address = ":8080"
[web.auth.basic]
users = ["toolbox:$basicauth"]

[docker]
domain = "xxx.yyy.net"
watch = true
swarmmode = true
exposedbydefault = false

If I start a simple web service with:

docker service create \
   --name web \
   --label traefik.port=2015 \
   --network traefik-net \
   --label traefik.frontend.auth.basic=test:$$2y$$05$$/lF1ypvhkljsaB1nxPLuOua5DT567JXE.D7n5fxmdky4MqUFUAYam ldaume/caddy

... curl leads to 401:

> curl -u test:test http://web.xxx.yyy.net
401 Unauthorized

Everything works without the basic auth label.
And it works with a compose file and docker stack.

Did I miss anything?

@tlwt

This comment has been minimized.

Copy link

commented Nov 30, 2017

@ldaume - put the label in single quotes and don't escape the password (unless there is a single quote in it).

Example below (I tested it):

user: myName
password: myPassword

--label 'traefik.frontend.auth.basic=myName:$apr1$a7R637Ua$TvXp8/lgky5MDLGLacI1e1' \

you can generate your own passwords using

 htpasswd -nbm myName myPassword
@jeroenvandergeer

This comment has been minimized.

Copy link

commented Nov 30, 2017

The label does not seem to be set properly when configured in a compose file, and when there's a period or slash in the hash. Quotes, single quotes or no quotes seem to not make a difference.

I've got this (test/myPassword):

- "traefik.frontend.auth.basic=test:$apr1$a7R637Ua$TvXp8/lgky5MDLGLacI1e1"

Results in:

"basicAuth":["test:/lgky5MDLGLacI1e1"]

Edit: A hash without any period or slash results in a empty label for me.

"traefik.frontend.auth.basic=test:$apr1$xiHBnyGR$LRais4AZRGxIKDRDpHW1h1"
"basicAuth":["test:"]
@tlwt

This comment has been minimized.

Copy link

commented Dec 1, 2017

I did not try it via docker compose, but rather via docker service create. That worked for me there ...

@ldez

This comment has been minimized.

Copy link
Member

commented Dec 1, 2017

@jeroenvandergeer replace all $ by $$ 😉

@tourshi

This comment has been minimized.

Copy link

commented Dec 25, 2017

Thank you @ldez
this helped me get my basic auth working, is there anyway to have this in the documentation to let anyone who is using docker-compose know that they should replace $ to $$

replace all $ by $$

Thanks!

@yayitswei

This comment has been minimized.

Copy link

commented Mar 16, 2018

I followed the suggestions above to replace $ with $$ and I'm still getting the parse error. Could someone post a working example docker-compose.yml file? FWIW I'm running docker swarm with traefik 1.5.4.

Thanks!

@dimisus

This comment was marked as off-topic.

Copy link

commented Sep 15, 2018

I haven't fully understood the issue, but using htpassword solved it for me. It seems traefik uses the same algo to unhash the passwords.

apt install apache2-utils
htpasswd -nb your_username "your_password_here"

You will receive the according hash

your_username:khrglahfslgkha345346

Copy paste it to your .toml or your docker-compose script.

Use your password (not the hash) and everything will work fine.

@Berndinox

This comment has been minimized.

Copy link

commented Sep 16, 2018

Example @yayitswei

version: '3'

services:
  cadvisor:
    image: sha1/cadvisor
    deploy:
      labels:
        - "traefik.port=8080"
        - "traefik.docker.network=proxy"
        - "traefik.frontend.rule=Host:metrics.yourdomain.com"
        - "traefik.backend=cadvisor"
        - "traefik.frontend.entryPoints=http,https"
        - "traefik.frontend.auth.basic=User:$$PAss$word"
        - "traefik.frontend.passHostHeader=true"
        - "traefik.frontend.whiteList.sourceRange=1.2.3.4/32"
        - "traefik.frontend.whiteList.useXForwardedFor=true"
        - "traefik.frontend.headers.browserXSSFilter=true"
        - "traefik.frontend.headers.frameDeny=true"
        - "traefik.frontend.headers.customFrameOptionsValue=SAMEORIGIN"
        - "traefik.frontend.headers.STSSeconds=31536000"
        - "traefik.frontend.headers.STSIncludeSubdomains=true"
        - "traefik.frontend.headers.STSPreload=true"
      replicas: 1
    networks:
      proxy:
        aliases:
          - cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      #- /dev/disk/:/dev/disk:ro
      - /etc/localtime:/etc/localtime:ro



networks:
  default:
    driver: overlay
  proxy:
    external: true
@bitoffdev

This comment has been minimized.

Copy link

commented Mar 10, 2019

For people coming here in the future, this is an explanation.

Docker compose files support variable substitution. Both $VARIABLE and ${VARIABLE} syntax are supported. Read the official docs here

As a consequence, the content of your label is being mutated. Like most people have commented, you just need to replace '$' with '$$' to prevent variable substitution.

To generate credentials in the correct format, you could run:

htpasswd -Bbn test test | sed -e 's/\$/\$\$/g'

Explanation: The -B flag uses bcrypt, the -b flag uses the command line password, and the -n flag writes to standard output. Stream editor (sed) is used to double all the dollar signs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.