Customizing a Bucket's ACL

You can change the access control applied to a bucket by setting the bucket's ACL.

When a KiiObject inside a bucket is accessed, the KiiObject's ACL will be also checked.

Bucket ACL entries

A bucket ACL entry is composed of an action and a subject:

  • Action

    This item defines "what" the target user/group/thing can execute.

    Action Representation in code * What the target user/group/thing can execute
    CREATE_OBJECTS_IN_BUCKET bucketActionCreateObjects Create new KiiObjects in the bucket.
    QUERY_OBJECTS_IN_BUCKET bucketActionQueryObjects Query KiiObjects in the bucket.
    READ_OBJECTS_IN_BUCKET bucketActionReadObjects Read KiiObjects in the bucket.
    DROP_BUCKET_WITH_ALL_CONTENT bucketActionDropBucket Drop the bucket along with all KiiObjects inside.

    * These symbols are defined in the KiiACLAction enumeration and can be specified like KiiACLAction.bucketActionCreateObjects.

    Note: The "bucketActionReadObjects" action allows the subject to unconditionally read all KiiObjects in the bucket. For more information, see ACL Customization Examples.

  • Subject

    This item defines "who" can execute.

    Subject Who can execute the designated action?
    KiiUser instance The specified user.
    KiiGroup instance The members of the specified group.
    KiiThing instance The specified thing.
    KiiAnyAuthenticatedUser Any authenticated users.
    KiiAnonymousUser Anonymous users.

    See Subject for the definition of the "Any authenticated users" and "Anonymous users".

Managing a bucket's ACL

You can add and delete an ACL entry in a bucket's ACL. You can also get a list of ACL entries.

Adding a bucket ACL entry

Authorized subjects can add ACL entries to the ACL of buckets not in the application scope to add permissions (e.g., allowing anonymous users to create KiiObjects in the bucket). Only the app administrator can modify the ACL of buckets in the application scope (See the hint below).

You can also set an ACL entry to a non-existent bucket. In this case, the bucket will be auto-generated with the specified ACL entry.

Here is an example of adding two ACL entries to the ACL of a bucket in a user scope. In this example, the bucketActionQueryObjects and bucketActionCreateObjects actions are permitted to KiiAnyAuthenticatedUser.

Swift:

  • let bucket = KiiUser.current()!.bucket(withName: "my_private")
    
    var succeeded: NSArray?
    var failed: NSArray?
    
    // Create ACL entries.
    let entry = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionQueryObjects)!
    let entry2 = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionCreateObjects)!
    
    let acl = bucket.bucketACL
    
    // Set the ACL entries to the bucket ACL.
    acl.put(entry)
    acl.put(entry2)
    
    do{
      // Save the ACL to the server.
      try acl.saveSynchronous(&succeeded, didFail: &failed)
    } catch let error as NSError {
      // Handle the error.
      // Failed to update one ACL entry at least.
      // Check the error description and succeeded/failed arrays.
      return
    }
  • let bucket = KiiUser.current()!.bucket(withName: "my_private")
    
    // Create ACL entries.
    let entry = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionQueryObjects)!
    let entry2 = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionCreateObjects)!
    
    let acl = bucket.bucketACL
    
    // Set the ACL entries to the bucket ACL.
    acl.put(entry)
    acl.put(entry2)
    
    // Save the ACL to the server.
    acl.save { (acl : KiiACL , succeeded : [Any]?, failed : [Any]?, error : Error?) -> Void in
      if (error != nil) {
        // Handle the error.
        // Failed to update one ACL entry at least.
        // Check the error description and succeeded/failed arrays.
        return
      }
    }

Objective-C:

  • KiiBucket *bucket = [[KiiUser currentUser] bucketWithName:@"my_private"];
    NSError *error;
    NSArray *succeeded, *failed;
    
    // Create ACL entries.
    KiiACLEntry *entry = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionQueryObjects];
    KiiACLEntry *entry2 = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionCreateObjects];
    
    KiiACL *acl = [bucket bucketACL];
    
    // Set the ACL entries to the bucket ACL.
    [acl putACLEntry:entry];
    [acl putACLEntry:entry2];
    
    // Save the ACL to the server.
    [acl saveSynchronous:&error
              didSucceed:&succeeded
                 didFail:&failed];
    
    if (error != nil) {
      // Handle the error.
      // Failed to update one ACL entry at least.
      // Check the error description and succeeded/failed arrays.
      return;
    }
  • KiiBucket *bucket = [[KiiUser currentUser] bucketWithName:@"my_private"];
    
    // Create ACL entries.
    KiiACLEntry *entry = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionQueryObjects];
    KiiACLEntry *entry2 = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionCreateObjects];
    
    KiiACL *acl = [bucket bucketACL];
    
    // Set the ACL entries to the bucket ACL.
    [acl putACLEntry:entry];
    [acl putACLEntry:entry2];
    
    // Save the ACL to the server.
    [acl saveWithBlock:^(KiiACL *acl, NSArray *succeeded, NSArray *failed, NSError *error) {
      if (error != nil) {
        // Handle the error.
        // Failed to update one ACL entry at least.
        // Check the error description and succeeded/failed arrays.
        return;
      }
    }];
  1. Create a KiiACL instance of the bucket by calling the bucketACL() method.
  2. Create KiiACLEntry instances and pass them as the argument of the put(_:) method. Here, KiiAnyAuthenticatedUser instances are specified as the ACL entries' subjects so as to permit the actions to any authenticated users. If you set KiiAnonymousUser instances as the subjects instead, you can permit the same actions to anonymous users. If you set specific KiiUser instances, the actions will be permitted to those user instances.
  3. Call the save(_:) method to send the request for updating the ACL to Kii Cloud.

See KiiACLEntry for more information about how you can specify other subjects like users and groups.

When you are adding multiple ACL entries, the entry registration is handled one by one. If an error occurs before all entries are registered, some entries will remain unregistered. In such a situation, you can get a list of ACL entries that were succeeded and failed to register from succeeded and failed in the sample code.

Deleting a bucket ACL entry

To delete an ACL entry, create a KiiACLEntry instance with the grant argument set to false and save it. The ACL entry will be deleted from the server.

The following example deletes the ACL entries created in the previous sample code.

Swift:

  • let bucket = KiiUser.current()!.bucket(withName: "my_private")
    
    var succeeded: NSArray?
    var failed: NSArray?
    
    // Create ACL entries.
    let entry = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionQueryObjects)!
    entry.grant = false
    let entry2 = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionCreateObjects)!
    entry2.grant = false
    
    let acl = bucket.bucketACL
    
    // Delete the ACL entries from the bucket ACL.
    acl.put(entry)
    acl.put(entry2)
    
    do{
      // Save the ACL to the server.
      try acl.saveSynchronous(&succeeded, didFail: &failed)
    } catch let error as NSError {
      // Handle the error.
      // Failed to update one ACL entry at least.
      // Check the error description and succeeded/failed arrays.
      return
    }
  • let bucket = KiiUser.current()!.bucket(withName: "my_private")
    
    // Create ACL entries.
    let entry = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionQueryObjects)!
    entry.grant = false
    let entry2 = KiiACLEntry(subject: KiiAnyAuthenticatedUser.aclSubject(), andAction: KiiACLAction.bucketActionCreateObjects)!
    entry2.grant = false
    
    let acl = bucket.bucketACL
    
    // Delete the ACL entries from the bucket ACL.
    acl.put(entry)
    acl.put(entry2)
    
    // Save the ACL to the server.
    acl.save { (acl : KiiACL , succeeded : [Any]?, failed : [Any]?, error : Error?) -> Void in
      if (error != nil) {
        // Handle the error.
        // Failed to update one ACL entry at least.
        // Check the error description and succeeded/failed arrays.
        return
      }
    }

Objective-C:

  • KiiBucket *bucket = [[KiiUser currentUser] bucketWithName:@"my_private"];
    NSError *error;
    NSArray *succeeded, *failed;
    
    // Create ACL entries.
    KiiACLEntry *entry = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionQueryObjects];
    entry.grant = NO;
    KiiACLEntry *entry2 = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionCreateObjects];
    entry2.grant = NO;
    
    KiiACL *acl = [bucket bucketACL];
    
    // Delete the ACL entries from the bucket ACL.
    [acl putACLEntry:entry];
    [acl putACLEntry:entry2];
    
    // Save the ACL to the server.
    [acl saveSynchronous:&error
              didSucceed:&succeeded
                 didFail:&failed];
    
    if (error != nil) {
      // Handle the error.
      // Failed to update one ACL entry at least.
      // Check the error description and succeeded/failed arrays.
      return;
    }
  • KiiBucket *bucket = [[KiiUser currentUser] bucketWithName:@"my_private"];
    
    // Create ACL entries.
    KiiACLEntry *entry = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionQueryObjects];
    entry.grant = NO;
    KiiACLEntry *entry2 = [KiiACLEntry entryWithSubject:[KiiAnyAuthenticatedUser aclSubject] andAction:KiiACLBucketActionCreateObjects];
    entry2.grant = NO;
    
    KiiACL *acl = [bucket bucketACL];
    
    // Delete the ACL entries from the bucket ACL.
    [acl putACLEntry:entry];
    [acl putACLEntry:entry2];
    
    // Save the ACL to the server.
    [acl saveWithBlock:^(KiiACL *acl, NSArray *succeeded, NSArray *failed, NSError *error) {
      if (error != nil) {
        // Handle the error.
        // Failed to update one ACL entry at least.
        // Check the error description and succeeded/failed arrays.
        return;
      }
    }];

Note that the remove(_:) method of the KiiACL class just deletes an ACL entry from the local modification list. The method does not delete an ACL entry set on the server. In the above sample code, we first register requests to remove the bucketActionQueryObjects and bucketActionCreateObjects actions from acl on the client and then execute the save(_:) method to reflect the requests on the server. If you execute the remove(_:) method, it would remove these requests from the ACL modification list, but not from the ACL on the server.

Getting a bucket's ACL

You can get the ACL set on a bucket. Even if you have not set any ACL entries in a bucket's ACL, you can get its default ACL.

Here is the sample code for getting a list of ACL entries as an NSAarray.

Swift:

  • let bucket = KiiUser.current()!.bucket(withName: "my_private")
    let acl = bucket.bucketACL
    
    do{
      // Get the ACL entries from the server.
      let aclList = try acl.listACLEntriesSynchronous() as! [KiiACLEntry]
      for entry in aclList{
        let action = entry.action
        let subject = entry.subject
        // Check the ACL entry.
      }
    }catch(let error as NSError){
      // Handle the error.
      return
    }
  • let bucket = KiiUser.current()!.bucket(withName: "my_private")
    let acl = bucket.bucketACL
    
    // Get the ACL entries from the server.
    acl.listACLEntries { (retAcl : KiiACL, aclList : [Any]?, error : Error?) -> Void in
      if (error != nil) {
        // Handle the error.
        return
      }
      for entry in aclList as! [KiiACLEntry]{
        let action = entry.action
        let subject = entry.subject
        // Check the ACL entry.
      }
    }

Objective-C:

  • KiiBucket *bucket = [[KiiUser currentUser] bucketWithName:@"my_private"];
    
    KiiACL *acl = [bucket bucketACL];
    NSError *error = nil;
    
    // Get the ACL entries from the server.
    NSArray *aclList = [acl listACLEntriesSynchronous:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
    for (KiiACLEntry *entry in aclList) {
      KiiACLAction action = entry.action;
      id subject = entry.subject;
      // Check the ACL entry.
    }
  • KiiBucket *bucket = [[KiiUser currentUser] bucketWithName:@"my_private"];
    
    KiiACL *acl = [bucket bucketACL];
    
    // Get the ACL entries from the server.
    [acl listACLEntriesWithBlock:^(KiiACL *acl, NSArray *aclList, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
      for (KiiACLEntry *entry in aclList) {
        KiiACLAction action = entry.action;
        id subject = entry.subject;
        // Check the ACL entry.
      }
    }];
  1. Create a KiiACL instance of the bucket by executing the bucketACL() method.
  2. Call the listACLEntries(_:) method to get the bucket's ACL as a NSArray of the KiiACLEntry instances.
  3. Parse through each ACL entry in the NSArray.

Trying to set an existing ACL entry will give you an error. By checking existing ACL entries beforehand as shown in this sample code, you can find which ACL entries should be set.

Troubleshooting

  • I got an error when I run my application multiple times

    The ACL entry should be registered just once (e.g., in the initialization) and should not be registered again in the next run.

    If you try to save an existing ACL entry, you will get an error. If your application runs the same ACL entry registration flow every time, therefore, you will get an error because the application attempts to re-register an already existing ACL entry.

    When you are adding multiple ACL entries, the entry registration is handled one by one. If an error occurs before all entries are registered, some entries will remain unregistered. To recover from such a situation, you will first need to get a list of the existing ACL entries, remove the duplicating ACL entries from the ACL modification list, and then register remaining entries. See Getting a bucket's ACL to learn how to get the list of the existing ACL entries.

  • The subject is permitted the "bucketActionQueryObjects" action but failed to query KiiObjects in the bucket

    The bucketActionQueryObjects action only allows the subject to execute the query. To read the result (i.e., the KiiObjects queried), the subject also needs to have the privilege to read the KiiObjects.

    The easiest way to grant the privilege to read the KiiObjects is to permit the bucketActionReadObjects action to the subject together with the bucketActionQueryObjects action. This will allow the subject to read all KiiObjects in the bucket, so they will be able to read the query result.

    Alternatively, you can permit the objectActionRead action on the KiiObjects in the bucket. See KiiObject Access Control for more information about the KiiObject ACL.

    You can find the related discussion in ACL Customization Examples.

  • I cannot delete an ACL entry

    You cannot delete default ACL entries applied to scope owners and bucket creators. See Cannot delete default ACL entries of scope owners and creators for more details.

  • I cannot change the ACL of an application-scope bucket

    Changing the ACL of an application-scope bucket requires the app administrator privilege. Follow the procedure described in Admin Features to get an app administrator token and change the ACL with the steps described in Customizing a Bucket's ACL.

    For more information about who can change a bucket's ACL, see Bucket Access Control.