Access Control with .kbp_config
.kbp_config
is an optional json
-encoded configuration file. By default,
Keybase Pages enables reading and listing for the entire site. If you prefer to
turn off directory listing, or want a simple ACL control using HTTP Basic
Authentication, you can create such a
file at the root of your site. For example if your site is configured to
"kbp=/keybase/private/alice,kbpbot/my-site"
, .kbp_config
should be at
/keybase/private/alice,kbpbot/my-site/.kbp_config
.
To make editing the config file easy, we have a command-line tool that can completely replace editing .kbp_config by hand.
Install it with go get
:
go get -u github.com/keybase/client/go/kbfs/kbpagesconfig
kbpagesconfig
operates on (creates if needed) .kbp_config
in the current
directory, so typically you can cd
into the site root and use it:
$ cd /keybase/private/yourname,kbpbot/my-site
$ kbpagesconfig ...
Or override the directory using -d
flag:
$ kbpagesconfig -d /keybase/private/yourname,kbpbot/my-site ...
Watch this asciinema recording or continue reading for some examples!
How Keybase Pages uses .kbp_config
If .kbp_config
exists, Keybase Pages servers assume a predefined structure
composed of mainly two parts, a user map for users
and (bcrypt'ed) password
pairs, and an acls
map that defines permissions on each specified path. When
a Keybase Pages server (kbpagesd
) receives an incoming request for the site,
it roughly goes through the following steps:
-
Try to authenticate the request using HTTP Basic Authentication, and map the request to either anonymous, or a pre-defined user.
-
Look for the ACL in the config that most accurately matches the requested path. So for example if the only entry is
/
, it matches everything. If/foo
is also defined, then that's used for/foo
and everything under it, and/
is used for everything else. -
Use the ACL to decide whether the mapped user has sufficient permission on the requested resource. For a directory without
index.html
, thelist
permission is required. Otherwise, theread
permission is required. -
If needed, respond with HTTP status code 401, and a
WWW-Authenticate
header to request for Basic Authentication. Otherwise return the resource.
The ACL object for each path has two fields:
-
anonymous_permissions
, which defines the permission(s) that all visitors have on the give path. This applies to anonymous traffic that's not authenticated, as well as requests that have HTTP Basic Authentication headers. -
whitelist_additional_permissions
, which defines additional permissions that authenticated users can get on the given path, in addition to what's inanonymous_permissions
.
Putting them together, .kbp_config
has the following format in json
form:
{
"version": "v1",
"users": {
<username>: <bcrypt_password>,
...
},
"acls": {
<path>: {
"whitelist_additional_permissions": {
<username>: <"read"|"list"|"read,list">,
},
"anonymous_permissions": <"read"|"list"|"read,list">
},
...
}
}
Examples
Default Config
If the .kbp_config
is missing for a site, Keybase Pages uses a default config
that allows read
and list
permissions on the entire site, a.k.a.:
{
"version": "v1",
"users": {},
"acls": {
"/": {
"whitelist_additional_permissions": null,
"anonymous_permissions": "read,list"
}
}
}
/friends
and /no-listing
Here is a more complete example with the users
map populated and referenced
in acls
, where only alice
is allowed to access /friends
, and directory
listing is disabled on /no-listing
:
Using kbpconfig
:
$ kbpagesconfig user add alice # adds user "alice"; this'll prompt for a password
$ kbpagesconfig acl set default "" /friends # removes default (anonymous) permissions on /friends and its sub-directories
$ kbpagesconfig acl set additional alice "read,list" /friends # gives "alice" read and list permissions
$ kbpagesconfig acl set default "read" /no-listing # overrides the default (anonymous) permission for /no-listing to `read`, i.e. removing `list`.
In json
:
{
"version": "v1",
"users": {
"alice": "$2a$10$Z3eJqq2H3nQUvvBNkUEvLuWo9nHivPvSjlXLcQI6rZvUNebJ7rEBG"
},
"acls": {
"/": {
"whitelist_additional_permissions": null,
"anonymous_permissions": "read,list"
},
"/friends": {
"whitelist_additional_permissions": {
"alice": "read,list"
},
"anonymous_permissions": ""
},
"/no-listing": {
"whitelist_additional_permissions": null,
"anonymous_permissions": "read"
}
}
}