CloudKit security model is barely described in documentation, yet it's very important aspect of this cloud solution. I do care about privacy and I believe privacy aspect is important when implementing Cloud driven solutions. The subject is not widely explained in documentation, hence I'm writing this blog post as a notes for future me - with all the important information I was able to gather.
Security roles works like ACL (Access Control List). In this case it is more like RBAC (Role-based access control). It is an approach to restricting system access to authorized users, though CloudKit model allows to restrict access to unauthorized users as well.
I can setup C(reate)R(ead)U(update) access for each Record Type (if you're not familiar with terminology of CloudKit, think about Record Type as it would be database table).
Security Role gain/revoke access to each of three operations:
- read - Allows reading record
- create - Allows creating new records
- write - Allows editing and deleting records
permissions are additive.
I may assign Permission to Role, then Role to Record Type - this way I build access control list:
There is more... world and everyting.
In addition to custom security roles, there are 3 predefined roles:
This need a little explanation.
World is for everyone. In practice this is everyone in the world, whether iCloud user or not. The access is public to everyone.
Authenticated is for any authenticated iCloud user. Authenticated means logged into iCloud. I need iCloud account and I have to be authenticated with my account.
Creator is for iCloud user that is creator of record. This Role is per record. If user Susan created record, and user Andy created another record - this Role allows each access to it's own records, and not to record created by another user (unless other security roles allows that).
Default setup allows for reading to anyone, creating new records for authenticated iCloud users only, and creating and updating own records by creators.
Public vs. private
Security roles apply to public databases. Private CloudKit database, by design is for private use only, and you can't allow access to it to anyone else. Effectively Security Roles apply to public database.
Add user to the role
I can't create user record. It is created whenever user authenticate to the container for the first time. I can lookup for the existing user (by any field) and assign to one of the custom Security Roles. Now the user permissions are specifically set up.
This can't be done automatically though.
Server setup will check the constraints. It's up to the application to care about the access, in general. When my application need to work on public database, and users have to operate on public records, It's my responsibility to limit the data.
If something is public (read) - then it is public.
Authenticated users can access to public data through the application. That is, application is certified to access to container assigned to the application. That means (unless I allow for that) no third party applications have access to create or modify records in public database. My application is the only gateway to the database.
The same apply to access via CloudKit Web Services. Server, by default is not the super user. I have to either authenticate with the user, or have special role assigned to my user to perform any operations.
Security Roles are part of data model, as such I have to deploy it to Production schema. Whenever I modify security setup, I have to deploy it to the production database to make it effective there. This has all drawbacks of deployment (Can't delete security role after deployment).
Database is protected
Database data is protected from the Apple employees and any other authorities. They can't lookup my records - don't have this authority by design. It's all encrypted, as it is standard for iCloud.