I mentioned in my last post
that I’ve extended the range of permissions that can
be set with the perms command to cover the whole gamut.
Here, I’ll describe this in the context of showing how I
have set up permissions for the fish user to make them suitable
for use with the online version of
fish—shell-fish.
My goal was this. Shell-fish, the online version of fish, allows
users to log in with their Google account and effectively link it to
one or more Fluidinfo accounts. Users who do this can use fish to
perform arbitrary Fluidinfo operations using their own tags. But I
also wanted to allow users to try out Fluidinfo and fish without
setting up an account. Initially, I did this using the Fluidinfo
test user, but that’s probably not a good long-term solution. What
I’d prefer to do is to provide a locked down account that anyone can
use for certain things—not only for reading but also to try out tagging.
The process of locking down a Fluidinfo account is also useful as an
illustration of the extended perms command in fish,
so that is the subject of this post.
I created the Fluidinfo fish user and switched to it in fish.
$ fish su fish
Credentials set to user fish.
$ fish ls -ld fish
nrwcr--r-- fish/
As you can see the permissions on fish’s namespace are the defaults,
with the user having read, write and control permission, and everyone
else having read only. (See this post or the
fish documentation for the ls command).
The first thing I wanted to do was to transfer control permission
from the fish user to me (njr) so that a user of Shell-Fish
can’t do arbitrary things. This wasn’t possible with the original
perms command, but I’ve added three new forms of the command,
each of which follows the general template:
fish perms perms-class [open|closed] [except list+of+users] list of tags or namespaces
where perms-class is one of read, write or control.
This simply lets the user set the explicit FLuidinfo permissions,
as open or closed, with an optional exception list.
The exception list is specfied as a list of users, separated by +
signs. The command only changes the permissions class specified
and changes all the permissions in that class for the tags or namespaces
given. So valid examples operating on a tag fish/rating and
a namespace fish/private include:
fish perms read closed except fish fish/rating fish/private
fish perms write closed fish/rating fish/private
fish perms control closed except fish+njr fish/rating fish/private
To transfer the control permissions to njr for the top-level fish namespace,
I used the command (still as the fish user at this point):
$ fish perms -f control closed except njr fish
The only extra thing to notice here is the -f flag, which forces
fish to make a change it would otherwise resist. Any change to
permissions that results in the owner of a tag or namespace not having
control permissions falls into this category, and since this is usually
undesirable, fish requires the -f flag to force this to happen.
(Tranferring permission to njr is, of course, irreversable for fish.)
Having made this change, if we repeat the ls command we see this:
fish ls -ld fish
(denied) fish/
Fluidinfo allows only users with control permission to see the
permissions on tags and namespaces, so the fish user can no longer see
them. (I suppose this is slightly odd: it means that you can’t even
see that you have write permission if you don’t have control permission.
But that’s not a huge problem.)
Let’s switch to njr and try.
$ fish su njr
Credentials set to user njr.
$ fish ls -ld fish
nrw-r-cr-- fish/
This is as expected. The owner—fish—no longer has control
permission on the fish namespace, but someone in a group does.
We know that someone is njr. (We could verify this with ls -L,
as we will after making some more changes.)
So far so good.
In terms of writing, my initial idea is to provide a set tags with
single-letter names (a to z) in fish‘s top-level namespace
that fish can write, but not to allow other tags or namespace
to be written.
First, let’s create those tags as the fish user.
$ fish su fish
Credentials set to user fish.
$ fish -U touch a b c d e f g h i j k l m n o p q r s t u v w x y z
The touch command on a non-existent tag creates the tag, and the -U
says use Unix-style paths, i.e. assume they’re in the authenticated
user’s namespace unless introduced with a leading /.
So this creates the 26 single-letter tags I want.
Next, we need to remove write permission from fish on the fish namespace,
so that it can’t create new tags or namespaces.
$ fish su njr
Credentials set to user njr.
$ fish perms write closed except njr fish
$ fish ls -ld fish
nr--rwcr-- fish/
Now let’s think about the permissions on the tags we have just created.
There is currently nothing hierarchical about Fluidinfo’s permissions.
So switching back to the fish user, we see:
$ fish su fish
Credentials set to user fish.
$ fish ls -l
trwcr--r-- fish/a
trwcr--r-- fish/b
...
trwcr--r-- fish/z
So even though njr has control of the fish namespace, the fish
user has control of the tags it created.
I don’t want that, so let’s transfer them over:
$ fish -U perms -f control closed except njr a b c d e f g h i j k l m n o p q r s t u v w x y z
$ fish ls -l a
trw-r-cr-- fish/a
[Again, the -U saves me having to prefixed each tag with njr/.
Of course, adding globbing (wild-carding) to fish would be even
more helpful; I’ll probably do that soon, though interaction with the
Unix shell’s globbing will be a slight issue there.]
So this is pretty good: the fish user has read and write permissions,
njr has read and control, and everyone else has read only.
The one remaining problem is that there are several different write
permissions on tags—permission to tag things with the tag (in native
Fluidinfo API terms, create permission on /tag-values),
permission to untag objects currently tagged with the tag (delete
permission on /tag-values) permission to change the description of
the tag (update permission on /tags) and permission to
delete the tag itself (delete permission on /tags). The
last of these is the problem: I don’t really want a random user of the
Shell-fish tags to be able to delete any of fish/a to fish/z.
To start with, fish couldn’t recreate them (because I’ve removed
write permission from fish on the fish namespace) and if it
did, fish would get control permission over that tag, which is
what I’ve been trying to avoid. So I need to remove the fine-grained
Fluidinfo permission to annihilate the tags from fish.
In order to allow this, I added a -X option to the perms
command. This “eXtra” specification restricts which particular
permissions within the class specified should actually be modified.
-X is followed by the fish name for a low-level Fluidinfo
permission, as shown in the ls -L “longer” listing. Let’s look at
the detailed permissions on one of our tags:
$ fish su njr
Credentials set to user njr.
$ fish ls -L /fish/a
fish/a:
ABSTRACT TAG (/tags)
Write
update (metadata): policy: closed; exceptions = [fish]
delete (delete): policy: closed; exceptions = [fish]
Control
control (acontrol): policy: closed; exceptions = [njr]
TAG (/tag-values)
Read
read (read): policy: open; exceptions = []
Write
create (tag): policy: closed; exceptions = [fish]
delete (untag): policy: closed; exceptions = [fish]
Control
control (tcontrol): policy: closed; exceptions = [njr]
Here, the Fluidinfo name for the low-level permission is shown
first, and then parentheses, the fish name is shown.
The fish names are unique for each kind of permission that exists
on tags, and the one we are concerned with is the ability to
delete the tag itself—the abstract tag. This has the same name,
delete, in both systems. So I used the command:
$ fish perms -f write -X delete closed except njr /fish/a
$ fish ls -L fish/a
fish/a:
ABSTRACT TAG (/tags)
Write
update (metadata): policy: closed; exceptions = [fish]
delete (delete): policy: closed; exceptions = [njr]
Control
control (acontrol): policy: closed; exceptions = [njr]
TAG (/tag-values)
Read
read (read): policy: open; exceptions = []
Write
create (tag): policy: closed; exceptions = [fish]
delete (untag): policy: closed; exceptions = [fish]
Control
control (tcontrol): policy: closed; exceptions = [njr]
As you can see, this changed only the delete permission from
the specified write class, which is what we wanted. (If I had
wanted to change several, I could have repeated the -X option.)
I repeated this using the other 25 tags. If we now look at
the result using ls -g, we get this:
$ fish ls -g /fish
tr/-r/cr-- fish/a
tr/-r/cr-- fish/b
...
tr/-r/cr-- fish/z
Reading across:
- The t means that this is tag
- The r/- means that the tag’s owner, fish, has read and some
write permissions on the tag—in this case, all except the
delete permission on the abstract tag
- The r/c means that there is some group of users with control
and read permissions, but only some write permissions. That group
is in fact the singleton [njr], and he has delete permission
only. (I could have actually just made the delete policy
closed—no one needs to be able to delete the tag, and I have
control anyway. Equally, I could have given myself all the other
write permissions; but I didn’t.)
- The final r-- means that the world has read permission, but not
write or control.
So that’s it. The fish user can now tag and untag things using
the tags fish/a through fish/z but has no ability to create
other tags or namespaces, or delete the tag itself, and does not have
control permission. The fish user can also in principle change
tag descriptions, though fish doesn’t provide a way of doing that
for existing tags right now.
I have just switched over shell-fish to use the fish user for
non-authenticated users, so you can try this out now. In passing, if
you use ls to list the fish namespace, you’ll see this:
_static/ genindex.html mkdir.html s unixlike.html
a h mkns.html search.html untag.html
b help.html n searchindex.js v
c i o show.html version.html
cli.html index.html p su.html w
commands.html install.html perms.html t whoami.html
count.html j pwd.html tag.html x
d k pwn.html tags.html y
e l q test.html z
f ls.html r touch.html
g m rm.html u
If you’re wondering what all these tags-that-look-like-web-pages are,
they’re tags that I use to store the HTML fish documentation in Fluidinfo
itself. If you look carefully at the documentation
path — http://fluiddb.fluidinfo.com/about/fish/fish/index.html — you
will see that its root is a tag on the Fluidinfo object having the
about tag fish. The name of that tag is fish/index.html,
and its content is the HTML for the index page. The trick lies partly
in the tag name and partly in setting its content type to text/html.
I have a script that does that, which will probably become a fish
command called Something like upload or publish or files2fi.