(This will eventually be published on the SwiftStack blog)
Preface: I am a developer at SwiftStack, where we work with Swift, which is in this context an open source distributed object storage engine, not the Apple language of the same name (which is also pretty cool, tbh, even if the compiler was a piece of shit when I was playing with it). Anyway, people who interact with Swift frequently run into trouble understanding the distinction between users and accounts (and for good reason; it’s quite confusing for the neophyte); so frequently, in fact, that I wrote up this blog post in order to have something to point people to.
This is written from the perspective of a SwiftStack developer to a SwiftStack customer, so it will sound somewhat odd appearing on this blog. When reading, I advise you to imagine yourself as a SwiftStack customer.
On a welcome rainy day not so long ago, I was sitting in the SwiftStack office and ruminating over how best to communicate with one of our valued customers about a feature said customer was interested in us implementing. In the course of coming to a more complete understanding of what was needed to fulfill this customer’s desires, I realized that I was having communication troubles as a result of the confusion between Users and Accounts in Swift. In addition to this already difficult terminology — people are often used to saying “user account” in the context of other software, which leads them to (not irrationally!) misunderstand the crucial distinction inside of Swift — there is also the extra level of indirection of the fact that you yourself are a SwiftStack user!
Note: I will be using bold text for User and Account throughout when they refer to the concepts in Swift. If you see either term unbolded, it is being used to some other purpose.
So to start off with, I am going to indulge in some unbearable pedantry in the form of terminology.
- Swift User — Swift has a concept of users which are tied to authentication and authorization. A Swift User does not, on its own, provide any access to the storage engine. Instead, it is a way to take credentials from a client and allow Swift to recognize that, yes, indeed, I am aware of this user, and if they continue to make other requests, I have the means to authorize (or refuse to authorize) those requests.
- Swift Account — An Account, on the other hand, is simply the top-level namespace for storage inside Swift. An Account may have many Containers, each of which may have many Objects, as you are no doubt aware. However, an Account is not necessarily tied to a Swift User.
- SwiftStack User — This is your identity on the SwiftStack Controller, which is in no way connected to your or anyone else’s Swift user (or Account, of course!)
The last of these is fairly easy to understand as separate from the others, and is generally confusing because of sloppy terminology when speaking about it (in particular, the fact that our auth system for Swift is called SwiftStack Auth, thus necessitating at times the phrase “SwiftStack Auth Swift User” to wholly disambiguate from a SwiftStack Controller user). I thought it was worth calling out explicitly if only to explain that I’m not going to be discussing what a SwiftStack user is.
On the surface, the concepts of User and Account seem fairly easy to distinguish between: a User represents a human (or maybe an automated service), who “logs in” to Swift and then has permissions to see various things. An Account is sort of like a folder, in that you can put Containers in it and then Objects in those Containers. So what’s the problem?
Well, I think the problem comes from a few things. The primary two are:
- Simple bad pedagogy and sloppy language on the part of Swift experts, and
- The fact that Accounts are, in many auth middlewares, auto-vivified per user.
Problem 1 is something that I myself am guilty of. When talking with other developers and people immersed in Swift, if I slip up and say “user account” when I mean “user” or similar, my colleagues have no difficulty in translating it within context to whatever I actually meant. However, in letting such imprecise language slip into conversations where I’m trying to understand a problem a customer is having, I only create more confusion for both of us.
Cause 2, however, is not something I can label a problem on its own. It’s actually quite a convenient thing! It would be more difficult to get started using a Swift cluster if you had to not only create a User, but then also explicitly create an Account for that User (or perhaps give them permissions to create their own Account). However, people often just start using Swift without ever being taught about the distinction between Users and Accounts, and so the lines get blurry because, in many people’s experiences, there’s a tight one-to-one correspondence between Users and Accounts.
So let’s talk first about the way many people interact with Swift, which leads to most of the confusion, and then we’ll get into other aspects of Accounts in general. When you authenticate with Swift using your username and password, you get back a response that includes, among other things, a Storage URL. This Storage URL is nothing but a link to the default Account that your User has access to. For example, in SwiftStack Auth (our auth system for Swift, not for the SwiftStack Controller), if you authenticate as User “Alexander”, you’d get back a storage URL that looks like
http://swift.example.com/v1/AUTH_Alexander. That last bit, the
AUTH_Alexander, is the name of my Account! In this case, it was automatically created for me by SwiftStack Auth, which by default creates an account for each User, and gives that User full ownership of the Account. Now, if I make a request to that Storage URL, I get back a fairly bland response; I have no objects and no Containers. But I am free to change that – this is my Account, after all!
On the other hand, what if I try to request a similar URL, but with a different final segment; that is, try to access a different Account? Well, when I try to access the account AUTH_Brenda, I get back a 403 Forbidden error response, because I do not have access to Brenda’s data.
Now let’s briefly talk about superusers. If you’re using SwiftStack Auth to create Swift Users, you’ll notice there is a checkbox for making a user a superuser. A superuser has access to all data inside the Swift cluster. If I created a new User named Superman for my cluster, and had Superman set up and authenticated as a superuser, I would be able to see I would be able to see all of Alexander’s or Brenda’s data.
In fact, I can go ahead and outright delete Alexander and Brenda’s Swift Users, so that it is no longer possible to authenticate using their credentials, and Superman will still be able to see and act upon any data that either of them had put in the cluster!
Superusers are not the only way to access Accounts other than the one your User implicitly has ownership of; you can also set up what are called Access Control Lists (ACLs) on Accounts and Containers, for example. This post is already quite long enough without going into detail on other ways to divorce Users and Accounts, though!
I hope this helped you understand a little bit better the difference between Users and Accounts in Swift. The takeaway is that the two are not closely tied together except by convention and for your convenience.