MySQL solves a bunch of problems for us. I have noticed the following problems with our authentication system:
We cannot tell when users were added easily
300+ users is very hard to manage with /etc/passwd and /etc/shadow
There is no reasonable way to keep track of user bans, a point system makes this automatic
We can easily attach more data to a user than is possible with the standard unix authentication (notes, etc)
This is much cooler!
Here is some documentation we may need:
The database layout will be similar in strategy of how the /etc/passwd and /etc/shadow system already works. There will be two accounts able to access the database, with two seperate sets of permissions. There will be an ‘nss_passwd’ user and an ‘nss_shadow’ user. The ‘nss_passwd’ user will be accessible by all users and will have the same access priviledges as a standard user would have to /etc/passwd and /etc/shadow, etc.
| Table Name | Permissions |
| passwd | read |
| group | read |
| group_members | read |
| shadow | – |
| gshadow | – |
| auth_log | – |
| user_meta | read |
| user_meta_shadow | – |
| user_notes | – |
| Table Name | Permissions |
| passwd | read, write |
| group | read, write |
| group_members | read, write |
| shadow | read, write |
| gshadow | read, write |
| auth_log | read, write |
| user_meta | read, write |
| user_meta_shadow | read, write |
| user_notes | read, write |
The passwd table is where the main user record is stored. This is similar to /etc/passwd but only stores vital information. This table also prevents a group from being deleted if it is the user’s default group.
| Name | Type | Options |
| uid | int(11) | NOT NULL |
| name | varchar(32) | NOT NULL |
| gid | int(11) | NOT NULL |
| created | timestamp | DEFAULT NOW() |
| Index/Key Name | Type | Notes |
| passwd.name | INDEX | |
| passwd.gid | INDEX | |
| passwd.uid | PRIMARY KEY | |
| gid_key | FORIEGN KEY | passwd.gid REFERENCES group.gid ON UPDATE CASCADE ON DELETE RESTRICT |
The group table store the main group record. This is similar to /etc/group but does not store group memebers.
| Name | Type | Options |
| gid | int(11) | NOT NULL |
| name | varchar(30) | NOT NULL |
| Index/Key Name | Type | Notes |
| group.name | INDEX | |
| group.gid | PRIMARY KEY | |
This tables store pairings of user ids to group ids. This represents what groups a user belongs to. The user id and group id columns will automatically be modified or deleted if a user or group is modified or deleted.
| Name | Type | Options |
| uid | int(11) | NOT NULL |
| gid | int(11) | NOT NULL |
| Index/Key Name | Type | Notes |
| group_members.uid | INDEX | |
| group_members.gid | INDEX | |
| uid_key | FOREIGN KEY | group_members.uid REFERENCES passwd.uid ON UPDATE CASCADE ON DELETE CASCADE |
| gid_key | FOREIGN KEY | group_members.gid REFERENCES group.gid ON UPDATE CASCADE ON DELETE CASCADE |
The shadow table is where users passwords are stored. This table is only readable/writable by the nss_shadow user. If a user is deleted or their uid is modified their record in this table will be deleted or modified accordingly.
| Name | Type | Options |
| uid | int(11) | NOT NULL |
| password | varchar(255) | DEFAULT NULL |
| points | int(11) | NOT NULL DEFAULT 0 |
uid - the user id that this shadow entry belongs to
password - the password (hashed) for this uid
points - the number of points this user has (note: this value is recalculated by nss_update_user_points)
| Index/Key Name | Type | Notes |
| shadow.uid | PRIMARY KEY | |
| uid_key | FOREIGN KEY | shadow.uid REFERENCES passwd.uid ON UPDATE CASCADE ON DELETE CASCADE |
This table stored the password for a group. If a group is deleted or its group id changed, this table will be updated automatically.
| Name | Type | Options |
| gid | int(11) | NOT NULL |
| password | varchar(255) | DEFAULT NULL |
| Index/Key Name | Type | Notes |
| gshadow.gid | PRIMARY KEY | |
| gid_key | FOREIGN KEY | gshadow.gid REFERENCES group.gid ON UPDATE CASCADE ON DELETE CASCADE |
This table is a log of every time a user attempts to login to the system. It does reference any other table to ensure that records are never deleted.
| Name | Type | Options |
| id | int | NOT NULL AUTO_INCREMENT |
| time | timestamp | DEFAULT NOW() |
| user | varchar(32) | NOT NULL |
| pid | int(11) | NOT NULL |
| host | varchar(255) | NOT NULL |
| message | text | NOT NULL |
id - the id of this message
time - the time the user logged in
user - the name of the user who logged in
pid - the process id the user logged in from
host - the host where the user logged in from
message - the description of the authentication attempt
| Index/Key Name | Type | Notes |
| auth_log.id | PRIMARY KEY | |
This table is used to store public meta data for each user. This includes things such as name and email. If a user is removed or a user’s uid changes, this table will be updated automatically.
| Name | Type | Options |
| uid | int(11) | NOT NULL |
| key | varchar(32) | NOT NULL |
| value | varchar(255) | NOT NULL |
uid - the user id whom this meta entry belongs to
key - the key of the meta data
value - the value of the meta data
| Index/Key Name | Type | Notes |
| user_meta.uid | INDEX | |
| user_meta.key | INDEX | |
| uid_key | FOREIGN KEY | user_meta.uid REFERENCES passwd.uid ON UPDATE CASCADE ON DELETE CASCADE |
| Name | Values | Description |
| first_name | UTF-8 Unicode string | The user’s first name, or an empty string |
| last_name | UTF-8 Unicode string | The user’s last name, or an empty string |
| email | RFC 2822, § 3.4.1 | The user’s email address, or an empty string |
| country | ISO 3166-1 alpha-2 | The country in which the user resides, or an empty string |
| languages | ISO 639-1, CSV | The languages that the user communicates in, or an empty string. First value is user’s primary/native language. |
| home | legal file system path | The user’s home directory. |
| shell | legal file system path to program | The user’s default shell. |
This table is used to store private meta data for each user. This includes things such as authorization information for other programs, and information required of all users but wished to be kept private. If a user is removed or a user’s uid changes, this table will be updated automatically.
| Name | Type | Options |
| uid | int(11) | NOT NULL PRIMARY KEY |
| key | varchar(30) | NOT NULL |
| value | varchar(255) | NOT NULL |
uid - the user id whom this meta entry belongs to
key - the key of the meta data
value - the value of the meta data
| Index/Key Name | Type | Notes |
| uid_key | FOREIGN KEY | user_meta_shadow.uid REFERENCES passwd.uid ON UPDATE CASCADE ON DELETE CASCADE |
| uid_index | INDEX | user_meta_shadow.uid |
| key_index | INDEX | user_meta_shadow.key |
| Name | Values | Description |
| txp_user_level | [0-6] | User privileges on the main nl.org blog, from none (0) to admin (6) |
This table is used to store notes about users. This is used to log user information such as activities admins performed for the user. It is also used to report malicous activities. Each not has a point value, the more points a user has, the closer they are to being banned. Notes that should not impact a users ability to log into the system should be assigned a point value of zero, notes that should result in the user being closer to a ban should be assigned a positive point value, revocation of points should be done by adding a note of negative point value, not by deleting notes. If a user is deleted then all of their notes will also be deleted. Users who are authors of notes (admins) cannot be deleted without modifying the user’s notes.
| Name | Type | Options |
| id | int(11) | NOT NULL AUTO_INCREMENT |
| created | timestamp | DEFAULT NOW() |
| uid | int(11) | NOT NULL |
| authorid | int(11) | NOT NULL |
| amount | int(11) | NOT NULL DEFAULT 0 |
| description | text | NOT NULL |
id - The note’s unique id.
created - the date and time the note was created.
uid - the user id whom this note belongs
authorid - the user id of the author of this note
amount - the amount of points this note is worth (can be positive or negative)
text - the message of the note, reason for giving points
| Index/Key Name | Type | Notes |
| user.id | PRIMARY KEY | |
| user.uid | INDEX | |
| user.authorid | INDEX | |
| uid_key | FOREIGN KEY | user_notes.uid REFERENCES passwd.uid ON UPDATE CASCADE ON DELETE CASCADE |
| author_key | FOREIGN KEY | user_notes.authorid REFERENCES passwd.uid ON UPDATE CASCADE ON DELETE RESTRICT |
| Parameter | Type | Description |
| user | varchar(32) | The name of the user to add to the system. |
| password | varchar(255) | The password (plaintext) for this user, or NULL to disable password. |
| groupname | varchar(255) | The name of the default group for the new user to belong to. |
| firstname | varchar(255) | The first name of the new user to add. |
| lastname | varchar(255) | The last name of the new user to add. |
| email | varchar(255) | The email address of the new user to add. |
| home | varchar(255) | The home directory of the new user. |
| shell | varchar(255) | The default shell of the new user. |
This method creates a new user with the given parameters above. Each new user starts with 0 points. If the new user should not be able to login with a password, a NULL password can be used. The user’s first name, last name, email address, home, and shell will be set in user_meta.
| Parameter | Type | Description |
| user | varchar(32) | The username of the user to remove from the database. |
Removes a user, and all attached data, including, group associations, notes, and meta data from the database. A user who is an author of a note cannot be deleted.
| Parameter | Type | Description |
| user | varchar(32) | The name of the user to retrieve, this can use MySQL LIKE clause wild cards. |
Gets the user(s) matching the username parameter. The name parameter may contain the MySQL LIKE wildcards. This returns entries from the passwd table.
| Parameter | Type | Description |
| name | varchar(32) | The name of the user to retrieve. |
Returns a user’s id, or zero if they are not in the passwd table.
| Parameter | Type | Description |
| user | varchar(32) | The username of the user to authenticate. |
| password | varchar(255) | The password of the user to challenge with. |
Determines whether the username and password given is valid. If the username and password combination is not valid, this procedure will return 0.
| Parameter | Type | Description |
| user | varchar(32) | The username to set the password. |
| password | varchar(255) | The password to set for the user. |
Sets the password for this user. If no entry exists in the shadow table for this user, a new entry is created.
| Parameter | Type | Description |
| user | varchar(32) | The username to set the default group for. |
| group | varchar(32) | The name of the group to set as the default group . |
This method sets the default group for the user.
| Parameter | Type | Description |
| system | int | Whether to retrieve the next available uid for a system (1) or regular (0) account |
This method returns an unused user id (highest uid in passwd table + 1). System user ids are less than 1000, regular ones are 1000 and higher.
| Parameter | Type | Description |
| name | varchar(32) | The name of the new group to add to the database. |
| password | varchar(255) | The password (plaintext) to associate with this group, or NULL for no password. |
Creates a new group in the database. A password can be used so users not in the group may gain group-only privileges if they know the password.
| Parameter | Type | Description |
| name | varchar(32) | The name of the group to remove from the database. |
Removes a group from the database, removing all users associated with the group from the given group. This procedure will not succeed if a user’s default group is set to the group being removed.
| Parameter | Type | Description |
| name | varchar(32) | The name of the group to retrieve, this can use MySQL LIKE clause wild cards. |
Gets the group(s) matching the groupname parameter. The name parameter may contain the MySQL LIKE wild cards. This returns matching entries from the group table.
| Parameter | Type | Description |
| groupname | varchar(32) | The name of the group to authenticate. |
| username | varchar(32) | The name of the user to authenticate. |
| password | varchar(255) | The password of the group to challenge with. |
Determines whether the user belongs to the group, or if the groupname and password combination is valid.
| Parameter | Type | Description |
| name | varchar(32) | The name of the group to set the password for. |
| password | varchar(255) | The password to set for the group, can be NULL. |
Sets the password for this group. If no entry exists in the gshadow table for this group, a new entry is created.
| Parameter | Type | Description |
| username | varchar(32) | The username to be added as a member of the given groupname. |
| groupname | varchar(32) | The groupname to add the given username to. |
Adds the given user as a member of the given group.
| Parameter | Type | Description |
| username | varchar(32) | The username to be removed as a member of the given groupname. |
| groupname | varchar(32) | The group to remove the given user from. |
This removes the given user from the given group. This procedure will fail if the user’s default group is group given.
| Parameter | Type | Description |
| system | int | Whether to retrieve the next available gid for a system (1) or regular (0) group |
This method returns an unused group id (highest gid in passwd table + 1). System group ids are less than 1000, regular ones are 1000 and higher.
| Parameter | Type | Description |
| user | varchar(32) | The username to set the meta data of. |
| meta | varchar(32) | The key of the metadata to set. |
| value | varchar(255) | The new value to set the metadata, or NULL to delete. |
| private | int | Whether this metadata is private, 1 if private, 0 otherwise. |
This sets metadata for a user. If there is not a username/key entry for the given user then a new entry is created. This will overwrite old metadata entries. If the value given is NULL this procedure will delete the metadata, if it exists. The private variable determines what table to use, either user_meta or user_meta_shadow (if private = 1).
| Parameter | Type | Description |
| user | varchar(32) | The username to get the meta data of, this can use MySQL LIKE clause wild cards. |
| meta | varchar(32) | The key of the metadata to get, this can use MySQL LIKE clause wild cards. |
| private | int | Whether to fetch private, or public meta data, 1 if private, 0 otherwise. |
This fetches metadata for a user. Both the name and meta can contain wild cards found in MySQL LIKE clauses and will operate as expected. The private variable determines what what table to use, either user_meta or user_meta_shadow (if private = 1). Note: You cannot get metadata from both tables at once.
| Parameter | Type | Description |
| name | varchar(32) | The username to assign this note to. |
| author | varchar(32) | The username of the author of the note. |
| message | text | The contents of this note. |
| points | int | The number of points assigned to this note. Postive, negative and zero values allowed. |
Adds a note to a user and then updates their points in the passwd table. Each note is assigned to a specific user and each note must have an author. Notes can have a negative, postive or neutral point value, if a user has too many points, they will automatically be banned. Notes should never be removed.
| Parameter | Type | Description |
| name | varchar(32) | The name of the user to update the points of. |
Recalculates a user’s points based on off the point values of their notes in the user_notes table. This value is reflected in the shadow table.
-
i dont think very pretty having the ‘type’ variable ;-D…. in all seriousness, i dont see why we need a type, points are points, they suck and the description should be more than enough to determine why they got points (side-note… this is the one time i wish there was a discussion page) ~
shadowarts
All of these tables should be in the same database, no shadow database, we will manage per table permissions ~
shadowarts
Should notes have a timestamp? Should groups have a time stamp of when they were created (like users do)? ~
shadowarts
There’s probably a lot more interesting metadata we can have. Ideas? ~
illicium
I’m not sure we should be able to have multiple meta data entries with the same name anymore honestly. How would we handle deleting them? Would you have to know their value? ~
shadowarts
feesh thinks that there should be a mysql.nonlogic.org subdomain, so if the mysql gets handled by another server (or if other servers need to connect to mysql), it won’t be a hassle.