ingress-nginx: Basic auth: Blowfish/Bcrypt password hashing doesn't work
Is this a request for help? Yes, but also might be a bug report
What keywords did you search in NGINX Ingress controller issues before filing this one? “bcrypt” “crypt_r() failed”
Is this a BUG REPORT or FEATURE REQUEST? BUG REPORT
NGINX Ingress controller version: nginx-ingress-0.22.1
Kubernetes version (use kubectl version):
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.6", GitCommit:"9f8ebd171479bec0ada837d7ee641dec2f8c6dd1", GitTreeState:"clean", BuildDate:"2018-03-21T15:21:50Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"9+", GitVersion:"v1.9.7-gke.6", GitCommit:"9b635efce81582e1da13b35a7aa539c0ccb32987", GitTreeState:"clean", BuildDate:"2018-08-16T21:33:47Z", GoVersion:"go1.9.3b4", Compiler:"gc", Platform:"linux/amd64"}
Environment:
- Cloud provider or hardware configuration: GKE
- OS (e.g. from /etc/os-release): Linux / Ubuntu 16.04 (Local)
- Kernel (e.g.
uname -a): 4.4.0-134-generic (Local) - Install tools: N/A
- Others: N/A
What happened: I want to enable basic auth so I created a htpasswd configuration with a bcrypt hash. However, when I sign in, I get an “internal server error” with the following log entry:
2018/09/27 16:37:18 [crit] 28296#28296: *98777 crypt_r() failed (22: Invalid argument), client: xxx.xxx.xxx.xxx, server: xxx.xxx.xxx, request: "GET /favicon.ico HTTP/2.0", host: "xxx.xxx.xxx", referrer: "https://xxx.xxx.xxx/"
What you expected to happen: Basic auth to work with bcrypt hashes, as described here: http://httpd.apache.org/docs/current/programs/htpasswd.html
Bcrypt should be supported by ingress-nginx, since md5, sha1 and crypt are not considered secure anymore for hashing passwords.
How to reproduce it (as minimally and precisely as possible):
I generated the htpasswd string using Go, like this:
import (
...
"golang.org/x/crypto/bcrypt"
)
...
username := "admin"
password := "nitJ4ln7NLDTL5XzMyPbpBXlEHJOSvF55FYIImBtinI="
bcryptHashedPassword, _ := bcrypt.GenerateFromPassword(
[]byte(password),
bcrypt.DefaultCost, // = 10
)
htpasswd := fmt.Sprintf("%s:%s", username, string(bcryptHashedPassword))
Which generates the following output (contains 128bit salt):
admin:$2a$10$iOQDUvSaEY2tiHaLk980luTKCxTZ9TiyEmiqtVx5R8m9zKTHRfqru
Which I encode to base64 and put into a Secret’s auth field:
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
data:
auth: YWRtaW46JDJhJDEwJGlPUURVdlNhRVkydGlIYUxrOTgwbHVUS0N4VFo5VGl5RW1pcXRWeDVSOG05ektUSFJmcXJ1
Which is reused by an ingress rule:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/auth-realm: Authentication required.
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-type: basic
name: myingress
spec:
rules:
- host: xxx.xxx.xxx
http:
paths:
- backend:
serviceName: someservice
servicePort: 3000
path: /
tls:
- hosts:
- xxx.xxx.xxx
When I open the site in a browser, if prompts for a password but returns a 500 error, with the log output shown above.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 15 (5 by maintainers)
Closing. This bug is related to the missing support for bcrypt in debian/ubuntu https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=149452 Once this is fixed upstream we can address this issue.
Can also confirm this works now.
Example Using Terraform to create the blowfish password:
Ingress Annotations
I can confirm that the latest version (0.27.0) works. Thank you!
Apache can support it 😃 I’m using Slackware 14.2 and have the same issue with nginx, but bcrypt passwords work fine in Apache
This would be a problem for FIPS environments, as the default password encryption is MD5, but FIPS bans all MD5.
The SHA1 implementation in “htpasswd” does not include a salt, so is vulnerable to a rainbow attack. Therefore, bcrypt is really the only secure password mechanism available.
You really should support bcrypt.