Cloud Connected

Thoughts and Ideas from the Gitana Development Team

Enterprise Access Policies in Gitana 4.0 (Part 2)

In this article, we'll continue our series on Access Policies within Gitana. We'll take a few interesting and more complex examples of how Access Policies may be used to guarantee compliance witih enterprise security requirements.

In the previous article, we left off looking at how you can grant access to content using Access Policies that are defined at either a Platform or Project-level. Platform-scoped policies can be written once and applied across all of your Projects. In this way, you can centrally manage Access Policies that are applied to Projects using regular expressions on the Project ID, title or a custom field.

Alternatively, you can assign them one-by-one to your Projects. Or allow Project Managers to manage their own Access Policies from within their Projects.

Let us extend on this and look at some new Access Policies that do interesting things!

Grant the Consumer Role to Specific Folders

Suppose you have a single Project. You've invited a vendor to the Project and you'd like to allow that vendor's users to be able to view a specific folder and all of its content. Suppose the vendor is ACME Corporation and the path to their resources is /resources/acme.

Let's use the path condition to define an Access Policy that does just this!

{
    "title": "Consumer of Content in Folder /resources/acme",
    "statements": [{
        "action": "grant",
        "roles": ["consumer"],
        "conditions": [{
            "type": "path",
            "config": {
                "path": "/resources/acme(.*)"
            }
        }]
    }]
}

That's it. We assign this Access Policy to the ACME team or group. And by doing so, all members of that team or group will be able to view the /resources/acme folder. It also means that those members will be able to perform full-text searches, GraphQL queries or any other API call within Gitana and read the content contained within that folder.

What if we wanted to define this Access Policy at the platform level and have it apply only to specific Projects? We can borrow the statements from the previous article's Access Policy and combine them here to build a multi-statement Access Policy that runs at the Platform level and can be used across multiple Projects!

{
    "title": "Consumer of Content in Folder /resources/acme",
    "statements": [{
        "action": "grant",
        "roles": ["consumer"],
        "conditions": [{
            "type": "path",
            "config": {
                "path": "/resources/acme(.*)"
            }
        }, {
            "type": "project",
            "config": {
                "property": "has_vendor_resources",
                "value": true
            }
        }]
    }]
}

In this way, this single Access Policy will work across multiple Projects. Specifically, it will work across Projects that have has_vendor_resources set to true.

It's worth noting that you can also limit the grant to the specific folder -without- granting for subfolder elements. For example, if you wanted folks to be able to see the acme folder but -not- see any sub-items, you can change the path to:

"path": "/resources/acme"

You can learn more about the path condition here:
https://gitana.io/documentation/gitana/4.0/engine/security/access-policies/conditions/path.html

Grant Consumer Role to Content on a Specific Branch

Gitana is unique in that it is one of the only content platforms that offers Git-like branches and versioning. Every change that your editorial team makes is captured. And editorial teams are empowered to work in branched workspaces, allowing them to make changes at the same time without stepping on each other's toes!

Your Access Policies can be scoped to work against all branches or against specific branches. The branch condition allows you to scope your Access Policy statements to branches as you please.

Here is an example where the Consumer role is granted to all nodes on the branch named My Workspace.

{
    "title": "Consumer of Content on the 'My Workspace' branch",
    "statements": [{
        "action": "grant",
        "roles": ["consumer"],
        "conditions": [{
            "type": "branch",
            "config": {
                "title": "My Workspace"
            }
        }]
    }]
}

We can also grant by Branch ID or by Branch alias. Here is a statement which uses an $or composite clause to allow for two cases:

{
    "title": "Consumer of Content on Two Branches",
    "statements": [{
        "action": "grant",
        "roles": ["consumer"],
        "conditions": [{
            "type": "or",
            "config": {
                "conditions": [{
                    "type": "branch",
                    "config": {
                        "id": "574118a48a2e68c897ed"
                    }
                }, {
                    "type": "branch",
                    "config": {
                        "alias": "authoring"
                    }
                }]
            }
        }]
    }]
}

Finally, we can also bind the Access Policies to any other property on a Branch (including custom properties) using the property and value options. Suppose our team of editors is kicking off branches left and right for various purposes. We can write our Access Policy to apply to those branches by simply saving them with a custom property. If each Branch had a property purpose with a value of daily_update, we could do something like this:

{
    "title": "Consumer of Content on Daily Update branches",
    "statements": [{
        "action": "grant",
        "roles": ["consumer"],
        "conditions": [{
            "type": "branch",
            "config": {
                "property": "purpose",
                "value": "daily_update"
            }
        }]
    }]
}

We can assign this Access Policy at the Project level to have it apply to all resources within a specific-Project. Or we can define it at the Platform level to have it work across all Projects. If we did that, we'd likely want to introduce additional conditions to selectively decide which Projects the Access Policy should apply to.

You can learn more about the branch condition here:
https://gitana.io/documentation/gitana/4.0/engine/security/access-policies/conditions/branch.html

Grant Consumer Role to Content by Node Type QName

Gitana provides a content modeling facility that lets you define the structure of your content types, content associations and features/aspects using JSON Schema. Everything is compiled at a branch-level, on-the-fly, as you make changes. Compile-time validators run to ensure that your content model is always consistent and valid. The system offers complete support for hierarchical inheritance, property-level overridess and even aspect-oriented feature injection against both content definitions and instances.

Your Access Policies are further able to scope their bindings to specific content definitions in your model. In this way, you can grant or revoke authorities against specific content types, letting you assign permission for teams to work on specific types or lineages of content in one fell swoop.

Suppose you wanted to allow Bill, Tina and Joe the ability to edit Press Releases. Your Press Releases might be implemented as a content type with the type QName of my:press-release. You could use the following Access Policy to grant the Editor authority:

{
    "title": "Editor of Press Releases",
    "statements": [{
        "action": "grant",
        "roles": ["editor"],
        "conditions": [{
            "type": "type-qname",
            "config": {
                "qname": "my:press-release"
            }
        }]
    }]
}

You would then put Bill, Tina and Joe onto a "Press Release Editors" team. Assign this Acccess Policy to the team and away you go!

You can learn more about the type-qname condition here:
https://gitana.io/documentation/gitana/4.0/engine/security/access-policies/conditions/type-qname.html

Grant Consumer Role to Content tagged with a Feature / Aspect

Gitana comes preloaded with a large number of features / aspects that you can use to inject important metadata and important behaviors onto your content instances and content types. Features are aspects that let you define concerns (behaviors / metadata) that you can snap into your content hierarchy from the side.

This provides a valuable tool that works seamlessly alongside hierarchical modeling! It allows you to snap in properties and behaviors that are centrally-managed. This injection effectively comes in from the side, instead of hierarchically, and lets you target any content definition within the tree.

For example, Gitana comes with a feature called f:watermarkable that can be marked onto a node to have that node's image attachment automatically undergo watermarking. That is to say, the node's original image has a watermark applied to it and the resulting image is added to the node as a new attachment.

Suppose you wanted to write a policy that granted Editor rights to all watermarked files. That's now very easy. You can do so like this:

{
    "title": "Editor of Watermarked Files",
    "statements": [{
        "action": "grant",
        "roles": ["editor"],
        "conditions": [{
            "type": "feature",
            "config": {
                "qname": "f:watermarkable"
            }
        }]
    }]
}

That's it. Assign this policy to a user to allow that user to edit all of the nodes with watermarked images in the system!

You can learn more about the feature condition here:
https://gitana.io/documentation/gitana/4.0/engine/security/access-policies/conditions/feature.html

Grant Editor Role to Translators for Localized Content

In Gitana, you use the f:multilingual feature to mark an individual content instance as supporting one or more multilingual translatons. Or, you can mark an entire Content Type within the dictonary so that all content instances of that type (or inherited types) will support multilingual translations.

Multilingual translations are stored within the content graph as associated nodes that contain the localized key/value pairs and the localized binary attachments for a given locale. Each associated node stores the localized data for a single translation. There is also no limit to the number of translations that a multlingual node may support!

You can modify individual translations manually or you can utilize our integrated AI services to automatically produce translated values for your properties. The central node in the graph structure is known as the "master node". You can set things up so that any changes to this master node will cause your localized content automatically translate using these integrated AI services.

Regardless of your approach, it is often the case that organizations will want to delegate either the editing of translations or the approval of automated translations to one or more translation teams. There may be one team of editors whose responsibility it is to manage all localized content. Or you may, for example, have multiple teams where one team is dedicated to Spanish content, another to German content and another to Chinese content.

Access Policies allow you to limit access rights to content based on the locale of the content. You can configure things so that everyone can see each other's content and translations while limiting which teams are specifically responsible for editing or approving the localized translations themselves.

Here is an Access Policy that grants Editor rights to content that has been localized to Spanish (where f:locale = es).

{
    "title": "Editor of Spanish Translations",
    "statements": [{
        "action": "grant",
        "roles": ["editor"],
        "conditions": [{
            "type": "locale",
            "config": {
                "locale": "es"
            }
        }]
    }]
}

And here is an Access Policy that does the same for Chinese (f:locale = zh).

{
    "title": "Editor of Chinese Translations",
    "statements": [{
        "action": "grant",
        "roles": ["editor"],
        "conditions": [{
            "type": "locale",
            "config": {
                "locale": "zh"
            }
        }]
    }]
}

You can learn more about the locale condition here:
https://gitana.io/documentation/gitana/4.0/engine/security/access-policies/conditions/locale.html

Learn More about Access Policies

This article and its predecessor really only scratch the surface regarding what is possible with Access Policies. We hope you've found it interesting! To learn more about Gitana, Access Policies and Content Modeling, please check out:

  • https://gitana.io
  • https://gitana.io/documentation/gitana/4.0/engine/content-models.html
  • https://gitana.io/documentation/gitana/4.0/engine/security/access-policies.html