De dónde proceden las personas
Un bloque user es el directorio entero de un sitio pequeño, o las cuentas de
servicio que uno grande mantiene fuera de su base de datos. Un sitio cuyas personas
ya están en una base de datos o en LDAP no debería copiarlas a un segundo lugar que
se quede desfasado, así que un bloque users las lee donde están. El bloque users
es el hcldir de go-authn/directory, el mismo que lee
go-fileshare: un mismo directorio se
describe igual para ambos.
Escritas en la configuración
user "alice" { password_file = "/etc/authnd/passwords/alice.pw" }
user "carol" {
nt_hash = "…" # MD4(UTF16LE(password)), 32 hex
authorized_keys = ["ssh-ed25519 AAAA… carol@laptop"] # published as sshPublicKey
}
group "staff" { members = ["alice", "carol"] }| campo | qué es |
|---|---|
password | la contraseña, en línea |
password_file | lo mismo, leído de un archivo (sin los espacios en blanco del principio y del final) |
nt_hash | MD4(UTF16LE(password)), 32 caracteres hexadecimales, para un sitio que guarda eso y no la contraseña |
totp_secret | un secreto de código de un solo uso en base32, de al menos 128 bits; consulte un segundo factor |
authorized_keys | líneas de authorized_keys, publicadas como sshPublicKey |
authorized_keys_file | lo mismo, a partir de un archivo |
attributes | desde la v0.11.0, lo que describe a la persona y no prueba nada —sn, uidNumber, gidNumber, homeDirectory, mail…—, como un mapa de cadenas o de listas de cadenas; un bloque group también lo admite. Deciden como qué se publica la entrada: consulte las entradas |
Se rechaza al arrancar, nombrando a la persona:
passwordypassword_filejuntos: indique cuál;passwordynt_hashjuntos: el hash se deriva de la contraseña, así que los dos pueden no coincidir;authorized_keysyauthorized_keys_filejuntos;- un
nt_hashque no tiene 32 caracteres hexadecimales, una línea deauthorized_keysque no se puede analizar, untotp_secretde menos de 128 bits; - el mismo
userogroupdos veces, y ungroupsin miembros.
Un miembro de grupo que ningún origen conoce también se rechaza, lo que detecta una errata antes de que, sin decir nada, no conceda nada:
$ authnd check cases/typo.hcl
authnd: group "staff" has "alise" in it, who is not in the configuration fileUn nt_hash solo no puede hacer un bind
Una persona escrita solo con nt_hash se publica, puede entregarse a un servidor
SMB mediante sambaNTPassword, y no puede hacer un bind con el propio authnd:
un bind simple de LDAP envía la contraseña, y un hash NT no es aquí una forma de
comprobarla. bob, más abajo, solo tiene un hash NT, y el hash es el de la contraseña
enviada:
$ ldapwhoami -x -H ldap://127.0.0.1:3893 -D uid=bob,ou=people,dc=example,dc=org -y bob.pwin
ldap_bind: Invalid credentials (49)check lo dice, después de las tablas:
bob and eli cannot bind with a password: their sources hold only what an SMB server needs (an NT hash), which a bind cannot be checked againstEn una base de datos SQL
users "sql" {
driver = "postgres" # or mysql (mariadb), or sqlite
dsn_file = "/etc/authnd/pg.dsn" # required: a DSN may hold a password
users = "select login, secret, nt_hash from staff" # required
groups = "select team, member from team_members" # optional
}Las consultas las escribe usted, porque las personas de un sitio ya tienen la
forma de ese sitio. Las columnas de la consulta users se leen por posición: un
nombre y, después, cualquiera de una contraseña, un hash NT, claves SSH (una por
línea) y un secreto de código de un solo uso, en ese orden, hasta cinco columnas. Un
NULL es una credencial que esa persona no tiene. Una columna de contraseña se compara
tal como está guardada: authnd no tiene ningún ajuste para una columna con hash. La
consulta groups devuelve un nombre de grupo y un miembro, una fila por pertenencia.
Otras dos consultas, opcionales, leen atributos por alias de columna en lugar
de por posición: users_attributes (un nombre y después una columna por
atributo) y groups_attributes (un grupo y después lo mismo). PostgreSQL pasa a
minúsculas un alias sin comillas. Consulte
las entradas.
driver acepta postgres (o postgresql, pgx), mysql (o mariadb) y sqlite
(o sqlite3). La base de datos se contacta al arrancar, antes de que nada escuche,
así que una que no responde detiene el servidor allí donde alguien está mirando:
$ authnd check cases/nodb
authnd: users "sql": the postgres database is not answering: failed to connect to `user=authnd database=authnd`:
127.0.0.1:1 (127.0.0.1): dial error: dial tcp 127.0.0.1:1: connect: connection refused
127.0.0.1:1 (127.0.0.1): dial error: dial tcp 127.0.0.1:1: connect: connection refusedPostgreSQL en la misma máquina, a través de su socket y de la autenticación peer,
no necesita ninguna contraseña en el DSN: host=/run/postgresql dbname=authnd user=authnd.
SQLite en el directorio de estado: file:/var/lib/authnd/people.db.
Una clave que pertenece a la otra clase de bloque se rechaza en lugar de ignorarse:
$ authnd check cases/sqlwrongkey.hcl
authnd: users "sql" has base_dn in it, which belongs to an ldap blockEn otro directorio LDAP
users "ldap" {
url = "ldaps://ldap.example.org"
base_dn = "ou=people,dc=example,dc=org"
bind_dn = "cn=reader,dc=example,dc=org"
bind_password_file = "/etc/authnd/upstream.pw"
}url y base_dn son obligatorios. Dónde están las personas y los grupos, y qué
atributos los nombran:
| clave | por defecto |
|---|---|
user_filter | (|(objectClass=posixAccount)(objectClass=account)(objectClass=uidObject)) |
user_attribute | uid |
group_base_dn | base_dn |
group_filter | (|(objectClass=posixGroup)(objectClass=groupOfNames)) |
group_attribute | cn |
group_member_attribute | ninguno: memberUid (nombres) y member (DN); si se define, es el único atributo que se lee |
totp_attribute | ninguno: no hay ningún atributo estándar, y uno adivinado no leería nada aparentando haber buscado |
attributes, group_attributes | ninguno: los atributos que se copian de la entrada de cada persona y de la de cada grupo, como ["mail", "uidNumber", "homeDirectory"] y ["gidNumber"] (las entradas) |
start_tls | false |
Un DN en member solo cuenta cuando es el DN de una entrada que devolvió la
búsqueda de personas: un DN fuera de ellas, o que no nombra a nadie, no
corresponde a nadie, y el nombre nunca se extrae del DN. sambaNTPassword y
sshPublicKey se leen con esos nombres.
Desde la v0.11.0, los valores por defecto leen más del directorio de una institución
El bloque es el de go-authn/directory, y directory v0.14.0, que incorpora authnd
v0.11.0, amplió sus valores por defecto: hasta la v0.10.2, user_filter era
(objectClass=posixAccount), group_filter (objectClass=posixGroup) y
group_member_attribute memberUid. Un directorio con entradas account o
uidObject que no son posixAccount —cuentas de servicio, máquinas nombradas
por uid, personas importadas de otro lugar— se las entrega ahora a authnd, y
cada una puede comprobarse con un bind; sus grupos groupOfNames pasan a ser
grupos aquí. Para conservar exactamente el conjunto anterior, escriba los
valores anteriores:
users "ldap" {
# ...
user_filter = "(objectClass=posixAccount)"
group_filter = "(objectClass=posixGroup)"
group_member_attribute = "memberUid"
}Dos cosas se rechazan antes de abrir nada:
$ authnd check cases/ldap-clear.hcl
authnd: users "ldap" would send every password to "ldap.example.org" in the clear: use ldaps://, or start_tls = true (RFC 4513 §5.1.3)
$ authnd check cases/ldap-cred.hcl
authnd: users "ldap" has credentials in its url, and a url is printed: use bind_dn with bind_password_fileldap:// hacia una dirección de loopback y ldapi:// se aceptan: no hay nadie en
medio.
Un directorio detrás de este comprueba las contraseñas haciendo un bind contra
él; no las entrega. Aquí un authnd hace de fachada de otro, bajo una base distinta;
el que está detrás es el ejemplo de
check,
servido en el 3893:
listen = "127.0.0.1:3894"
base_dn = "dc=example,dc=net"
users "ldap" {
url = "ldap://127.0.0.1:3893"
base_dn = "ou=people,dc=example,dc=org"
group_base_dn = "ou=groups,dc=example,dc=org"
bind_dn = "cn=reader,dc=example,dc=org"
bind_password_file = "etc/authnd/reader.pw"
}
user "svc-backup" { password_file = "etc/authnd/svc-backup.pw" }$ authnd check front2
ldap://127.0.0.1:3894, base dc=example,dc=net
USER FROM CAN PROVE PUBLISHED AS WITH
alice ldap://127.0.0.1:3893 a password check account, uidObject uid
bob ldap://127.0.0.1:3893 a password check account, uidObject uid
dora ldap://127.0.0.1:3893 a password check account, uidObject uid
eli ldap://127.0.0.1:3893 a password check account, uidObject uid
svc-backup the configuration file a password account, uidObject uid
GROUP MEMBERS PUBLISHED AS
engineers dora and eli groupOfNames
staff alice, bob and dora groupOfNames
alice has no uidNumber, gidNumber or homeDirectory: not a posixAccount, published as account, uidObject
bob has no uidNumber, gidNumber or homeDirectory: not a posixAccount, published as account, uidObject
dora has no uidNumber, gidNumber or homeDirectory: not a posixAccount, published as account, uidObject
eli has no uidNumber, gidNumber or homeDirectory: not a posixAccount, published as account, uidObject
svc-backup has no uidNumber, gidNumber or homeDirectory: not a posixAccount, published as account, uidObject
group engineers has no gidNumber: not a posixGroup, published as a groupOfNames (member DNs, no memberUid)
group staff has no gidNumber: not a posixGroup, published as a groupOfNames (member DNs, no memberUid)
a bind carries a password
no reader is declared: nothing may search, and binds are not affected
sambaNTPassword is not published, so nothing here can authenticate an SMB session (NTLMv2 needs the password or its MD4, and a bind cannot answer it)
this configuration can be servedCada persona que publica el directorio de detrás es un account y cada grupo un
groupOfNames, ya que ninguno tiene atributos POSIX: los valores por defecto
los leen, y los DN en member de los grupos corresponden a las personas
importadas. Con los valores por defecto de hasta la v0.10.2,
(objectClass=posixAccount) no habría encontrado a ninguna de ellas.
A password check basta para un bind, y nunca basta para un ticket Kerberos ni para SMB.
El orden, y la única excepción
Los orígenes se consultan en el orden en que están escritos, y el primero que
conoce un nombre se queda con él. Los bloques user siempre van primero, de modo que
una cuenta de servicio escrita localmente no la anula alguien con el mismo nombre en
la base de datos. La pertenencia a grupos es la unión de todos los orígenes:
un grupo que nombran a la vez un bloque group y la consulta groups de una base de
datos tiene los miembros de ambos.
Dos nombres que solo difieren en mayúsculas y minúsculas se rechazan
Un uid se compara sin distinguir mayúsculas de minúsculas (RFC 4519 §2.39), y lo
mismo ocurre con cada DN, así que Dora en el archivo y dora en una base de datos
son un solo nombre para LDAP y dos personas para todo lo que compara bytes: un cambio
de contraseña de una acabaría en la otra. Una configuración así no arranca:
$ authnd check cases/case.hcl
authnd: "Dora" (from the configuration file) and "dora" (from a sqlite database) differ only by case, and an LDAP name does not tell them apart: a uid is compared ignoring case. Rename one of themSe leen una vez
Cada origen se lee una vez, al arrancar. Una persona añadida a la base de datos, o una pertenencia modificada en el directorio que hay detrás de este, se sirve tras un reinicio, no antes. Eso incluye una columna de contraseña en una base de datos: se lee con el resto de la fila. Un directorio detrás de este solo se diferencia en que un bind se comprueba haciendo un bind contra él, así que la contraseña que funciona es la cambiada allí. La otra excepción es una contraseña que una persona cambia a través del propio authnd, que se aplica al instante. No hay recarga; consulte ejecutarlo.
Creada el por tannevaled
Modificada el por tannevaled