Skip to content

Commit 74ddac4

Browse files
Merge pull request #455 from codecrafters-io/auth-default
Revised Redis/Auth Instructions
2 parents 12c42a4 + 30ba625 commit 74ddac4

File tree

10 files changed

+524
-0
lines changed

10 files changed

+524
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
course_definition_tester
22
.history/
33
.idea/
4+
5+
# MacOS
6+
.DS_Store

course-definition.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,19 @@ extensions:
200200
[geoadd-command]: https://redis.io/docs/latest/commands/geoadd/
201201
[geosearch-command]: https://redis.io/docs/latest/commands/geosearch/
202202
203+
- slug: "authentication"
204+
name: "Authentication"
205+
description_markdown: |
206+
In this challenge extension you'll add support for default user [Authentication][redis-authentication] to your Redis implementation.
207+
208+
Along the way, you'll learn about commands like [ACL WHOAMI][acl-whoami-command], [ACL GETUSER][acl-getuser-command], [ACL SETUSER][acl-setuser-command], and [AUTH][auth-command], and more.
209+
210+
[redis-authentication]: https://redis.io/docs/latest/operate/oss_and_stack/management/security/
211+
[acl-whoami-command]: https://redis.io/docs/latest/commands/acl-whoami/
212+
[acl-getuser-command]: https://redis.io/docs/latest/commands/acl-getuser/
213+
[acl-setuser-command]: https://redis.io/docs/latest/commands/acl-setuser/
214+
[auth-command]: https://redis.io/docs/latest/commands/auth/
215+
203216
stages:
204217
- slug: "jm1"
205218
concept_slugs:
@@ -867,3 +880,60 @@ stages:
867880
name: "Search within radius"
868881
difficulty: easy
869882
marketing_md: In this stage, you'll add support for searching locations near a coordinate within a given radius using the `GEOSEARCH` command.
883+
884+
# Authentication
885+
- slug: "jn4"
886+
primary_extension_slug: "authentication"
887+
name: "Respond to ACL WHOAMI"
888+
difficulty: easy
889+
marketing_md: |
890+
In this stage, you'll add support for responding to the `ACL WHOAMI` command.
891+
892+
- slug: "gx8"
893+
primary_extension_slug: "authentication"
894+
name: "Respond to ACL GETUSER"
895+
difficulty: easy
896+
marketing_md: |
897+
In this stage, you'll add support for responding to the `ACL GETUSER` command.
898+
899+
- slug: "ql6"
900+
primary_extension_slug: "authentication"
901+
name: "The nopass flag"
902+
difficulty: easy
903+
marketing_md: |
904+
In this stage, you'll add support for responding to the `ACL GETUSER` command with the `nopass` flag set.
905+
906+
- slug: "pl7"
907+
primary_extension_slug: "authentication"
908+
name: "The passwords property"
909+
difficulty: easy
910+
marketing_md: |
911+
In this stage, you'll add support for responding to the `ACL GETUSER` command with the passwords property.
912+
913+
- slug: "uv9"
914+
primary_extension_slug: "authentication"
915+
name: "Setting default user password"
916+
difficulty: medium
917+
marketing_md: |
918+
In this stage, you'll add support for setting the default user's password.
919+
920+
- slug: "hz3"
921+
primary_extension_slug: "authentication"
922+
name: "The AUTH command"
923+
difficulty: medium
924+
marketing_md: |
925+
In this stage, you'll add support for responding to the `AUTH` command.
926+
927+
- slug: "nm2"
928+
primary_extension_slug: "authentication"
929+
name: "Enforce authentication"
930+
difficulty: medium
931+
marketing_md: |
932+
In this stage, you'll add support for enforcing authentication for the `default` user.
933+
934+
- slug: "ws7"
935+
primary_extension_slug: "authentication"
936+
name: "Authenticate using AUTH"
937+
difficulty: medium
938+
marketing_md: |
939+
In this stage, you'll implement enforcing authentication using the `AUTH` command.

stage_descriptions/auth-01-jn4.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
In this stage, you'll add support for responding to the `ACL WHOAMI` command.
2+
3+
### The `ACL WHOAMI` command
4+
5+
The [`ACL WHOAMI`](https://redis.io/docs/latest/commands/acl-whoami/) command is used to return the username the current connection is authenticated with.
6+
7+
In Redis, every new connection is automatically authenticated using the `default` user. This feature can be turned off, making every new connection unauthenticated at first. We'll get to that in the later stages.
8+
9+
Example usage:
10+
11+
```bash
12+
> ACL WHOAMI
13+
"default"
14+
```
15+
16+
It returns the username of currently authenticated user, encoded as a [RESP bulk string](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings).
17+
18+
### Tests
19+
20+
The tester will execute your program like this:
21+
22+
```bash
23+
$ ./your_program.sh
24+
```
25+
26+
It'll then send an `ACL WHOAMI` command.
27+
28+
```bash
29+
# Expect RESP bulk string: "default"
30+
$ redis-cli
31+
> ACL WHOAMI
32+
"default"
33+
```
34+
35+
The tester will validate that the response is the string `default`, which is RESP encoded as:
36+
37+
```
38+
$7\r\n
39+
default\r\n
40+
```
41+
42+
### Notes
43+
44+
- In this stage, you can hardcode the response of the `ACL WHOAMI` command to be `default`. We'll get to enforcing authentication in the later stages.

stage_descriptions/auth-02-gx8.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
In this stage, you'll add support for responding to the `ACL GETUSER` command.
2+
3+
### The `ACL GETUSER` command
4+
5+
The [`ACL GETUSER`](https://redis.io/docs/latest/commands/acl-getuser/) is used to retrieve the properties the specified user. In Redis, the `default` user is present from the start, without having to create it explicitly.
6+
7+
The `ACL GETUSER` returns multiple properties of the user, among which `flags` is one. In this stage, you'll add support for responding to the `ACL GETUSER` command with only the flags property.
8+
9+
Example usage:
10+
```bash
11+
> ACL GETUSER default
12+
1) "flags"
13+
2) (empty array)
14+
```
15+
16+
The second element of the resposne is the flags array. This is because a user can have multiple flags associated with it. In this stage, you can hardcode the flags array to be an empty array.
17+
18+
### Tests
19+
20+
The tester will execute your program like this:
21+
22+
```bash
23+
$ ./your_program.sh
24+
```
25+
26+
It'll then send an `ACL GETUSER` command specifying the `default` user.
27+
28+
```bash
29+
# Expect RESP array: ["flags", []]
30+
$ redis-cli
31+
> ACL GETUSER default
32+
1) "flags"
33+
2) (empty array)
34+
```
35+
36+
The tester will validate the following for the response:
37+
38+
1. The first element of the array is the string `flags`, encoded as a RESP bulk string.
39+
2. The second element of the array is a RESP array.
40+
41+
### Notes
42+
43+
- A user can have multiple flags. This is why the value of flags property is an array.
44+
45+
- The second element of the array is the flags array, which contains the user flags. We'll get to this in the later stages.

stage_descriptions/auth-03-ql6.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
In this stage, you'll add support for responding to the `ACL GETUSER` command with the `nopass` flag set.
2+
3+
### The `nopass` flag
4+
5+
The `nopass` flag is one of the user flags in Redis.
6+
7+
- If the `nopass` flag is set for a user, the authentication succeeds with an arbitrary password for the user.
8+
- Setting the `nopass` flag clears the associated passwords for the given user.
9+
- The default user has the `nopass` flag set. Due to this, new connections are automatically authenticated as the `default` user. (This behavior can be changed, and we'll get to this in the later stages.)
10+
11+
Example usage:
12+
```bash
13+
> ACL GETUSER default
14+
1) "flags"
15+
2) 1) "nopass"
16+
```
17+
18+
The flags are encoded as a RESP array of bulk strings. Each flag is a bulk string (e.g., `nopass`). We'll get to enforcing the behavior of the `nopass` flag in later stages.
19+
20+
In this stage, you only need to respond to the `ACL GETUSER` command with the `nopass` flag set.
21+
22+
### Tests
23+
24+
The tester will execute your program like this:
25+
26+
```bash
27+
$ ./your_program.sh
28+
```
29+
30+
It'll then send an `ACL GETUSER` command specifying the `default` user.
31+
32+
```bash
33+
# Expect RESP array: ["flags", ["nopass"]]
34+
$ redis-cli
35+
> ACL GETUSER default
36+
1) "flags"
37+
2) 1) "nopass"
38+
```
39+
40+
The tester will validate the following for the response:
41+
42+
1. The first element of the array is the string `flags`, encoded as a RESP bulk string.
43+
2. The second element of the array is a RESP array, and contains the `nopass` flag.

stage_descriptions/auth-04-pl7.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
In this stage, you'll add support for responding to the `ACL GETUSER` command with the passwords property.
2+
3+
### The `passwords` property
4+
5+
A user in the Redis ACL system can have zero or more passwords associated with them. The `ACL GETUSER` command also returns the `passwords` property of the specified user.
6+
7+
Example usage:
8+
```bash
9+
> ACL GETUSER default
10+
1) "flags"
11+
2) 1) "nopass"
12+
3) "passwords"
13+
4) (empty array)
14+
```
15+
16+
The fourth element of the response is the passwords array. The default user does not have any associated passwords unless explicitly configured. This is why the passwords array is empty for the default user.
17+
18+
### Tests
19+
20+
The tester will execute your program like this:
21+
22+
```bash
23+
$ ./your_program.sh
24+
```
25+
26+
It'll then send an `ACL GETUSER` command specifying the `default` user.
27+
28+
```bash
29+
$ redis-cli
30+
# Expect RESP array: ["flags", ["nopass"], "passwords", []]
31+
> ACL GETUSER default
32+
1) "flags"
33+
2) 1) "nopass"
34+
3) "passwords"
35+
4) (empty array)
36+
```
37+
38+
The tester will validate the following for the response:
39+
40+
1. The first element of the array is the string `flags`, encoded as a RESP bulk string.
41+
2. The second element of the array is a RESP array and contains the `nopass` flag.
42+
3. The third element of the array is the string `passwords`, encoded as a RESP bulk string.
43+
4. The fourth element of the array is an empty array because no passwords have been specified for the default user.

stage_descriptions/auth-05-uv9.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
In this stage, you'll add support for setting the default user's password.
2+
3+
### The `ACL SETUSER` command
4+
5+
The [`ACL SETUSER`](https://redis.io/docs/latest/commands/acl-setuser/) command can be used to modify the properties of an existing user. If this command is used with the `>` rule, it is used to add a password for the given user. Adding a password also clears the `nopass` flag from the user.
6+
7+
Example usage:
8+
9+
```bash
10+
> ACL SETUSER default >mypassword
11+
OK
12+
13+
> ACL GETUSER default
14+
1) "flags"
15+
2) 1) "nopass"
16+
3) "passwords"
17+
4) 1) "89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8"
18+
```
19+
20+
The response to the `ACL SETUSER` command is a RESP simple string: `+OK\r\n`.
21+
22+
The password array in the response of `ACL GETUSER` command contains one element and is the SHA-256 hash of the password `mypassword`.
23+
24+
Redis does not store the raw password specified in the `ACL SETUSER` command. Instead, it stores the SHA-256 hash of the password. While validating the password during authentication, the SHA-256 hash of the input password is calculated and matched against the stored list of SHA-256 password hashes. This is done because storing raw passwords is a security vulnerability.
25+
26+
### Tests
27+
28+
The tester will execute your program like this:
29+
30+
```bash
31+
$ ./your_program.sh
32+
```
33+
34+
It'll then send a `ACL GETUSER` command, specifying the `default` user
35+
36+
```bash
37+
$ redis-cli
38+
# Expect RESP array: ["flags", ["nopass"], "passwords", []]
39+
> ACL GETUSER default
40+
1) "flags"
41+
2) 1) "nopass"
42+
3) "passwords"
43+
4) (empty array)
44+
```
45+
46+
The tester will validate the following for the response of the `ACL GETUSER` command:
47+
48+
- The `nopass` flag is present in the flags array
49+
- The password array is empty
50+
51+
It'll then send a `ACL SETUSER` command, specifying the `default` user and a password.
52+
53+
```bash
54+
# Expect: +OK\r\n
55+
> ACL SETUSER default >mypassword
56+
OK
57+
```
58+
59+
The tester will validate that the response to the `ACL SETUSER` command is `+OK\r\n`.
60+
61+
It'll then send a `ACL GETUSER` command, specifying the `default` user.
62+
63+
```bash
64+
# Expect RESP array: ["flags", ["nopass"], "passwords", ["89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8"]]
65+
> ACL GETUSER default
66+
1) "flags"
67+
2) 1) "nopass"
68+
3) "passwords"
69+
4) 1) "89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8"
70+
```
71+
72+
The tester will validate the following for the response of the `ACL GETUSER` command:
73+
74+
- The `nopass` flag is not present in the flags array
75+
- The passwords array contains one element, and the element is the SHA-256 hash of the password, encoded as a RESP bulk string.
76+
77+
### Notes
78+
79+
- Redis uses the SHA-256 hashing algorithm for password storage. You'll need to compute the SHA-256 hash of the provided password and store it.
80+
81+
- The password hash should be stored as a lowercase hexadecimal string.

0 commit comments

Comments
 (0)