--- name: bcrypt_htpasswd kind: function lang: go domain: infra version: "1.0.0" purity: impure signature: "func BcryptHtpasswd(user, password string, cost int) (string, error)" description: "Genera una linea formato htpasswd para basicAuth de Traefik usando bcrypt. Si cost es 0 usa el default 10. Output: user:hash (sin escapado $$ — eso es solo para Docker labels en compose). Error si user o password vacios o cost fuera de [4,31]." tags: [bcrypt, htpasswd, auth, traefik, basicauth, infra, security] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [fmt, golang.org/x/crypto/bcrypt] params: - name: user desc: "nombre de usuario para la linea htpasswd (no puede ser vacio)" - name: password desc: "contrasena en texto plano a hashear con bcrypt (no puede ser vacia)" - name: cost desc: "factor de coste bcrypt en rango [4,31]; 0 para usar el default 10" output: "linea htpasswd con formato 'user:$2a$NN$...' lista para pegar en el file provider de Traefik o nginx" tested: true tests: - "hash valido pasa CompareHashAndPassword" - "formato es user:hash" - "cost cero usa default 10" - "error si user vacio" - "error si password vacio" - "error si cost fuera de rango" test_file_path: "functions/infra/bcrypt_htpasswd_test.go" file_path: "functions/infra/bcrypt_htpasswd.go" --- ## Ejemplo ```go line, err := BcryptHtpasswd("lucas", "s3cr3t", 10) // line = "lucas:$2a$10$..." // Pegar directamente en traefik-dynamic.yml bajo basicAuth.users ``` ## Notas La funcion usa `golang.org/x/crypto/bcrypt` (ya en go.mod). El salt aleatorio hace que cada llamada genere un hash distinto — la funcion es impura. El output es para el file provider de Traefik (single `$`). Para Docker labels en compose se necesita escapar a `$$`, lo que NO hace esta funcion. Verificacion: `bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))`.