Intro to Conjur Policy

Every Conjur workflow begins with a Conjur policy: whether tutorial, walkthrough, setup script, or how-to blog post, it has a security policy in it. That’s because everything in Conjur exists within a security context.

Security is a human concept that requires clear tools for communication. MAML policy (an acronym for “Machine Authorization Markup Language”) is the premier tool Conjur operators use to communicate about how your organization will grant access and maintain control. It’s security policy as code.

To start thinking with MAML let’s follow the story of Alice, a senior security engineer in a large hypothetical IT organization. She’s responsible for securing access to a database and she’s deploying open source Conjur.org to keep better control of the privileged database accounts.

1. Roles

Let’s start with the simplest MAML policy: a single user.

---
- !user alice

Alice loads this policy representing her user. For now, the user is given no access to anything, and the policy doesn’t define anything it could be given access to. But that’ll come later.

In Conjur, a user is a role in the sense of role-based access control. Each user represents one human being, like Alice. Her role implicitly has an associated secret: a Conjur API key. This is the only secret Alice needs to prove the authenticity of her identity. She can rotate her own API key and optionally set a password.

2. Resources & permissions

A user can be assigned permissions to access resources. Alice wants to store her production and admin passwords in Conjur, so she creates resources to represent them. Her policy looks like this:

---
- !user alice
- !variable database-password
- !variable database-admin-password

- !permit
  role: !user alice
  privileges:
    - read
    - execute
    - update
  resources:
    - !variable database-password
    - !variable database-admin-password

Alice’s policy models the infrastructure she’s responsible for securing as a set of roles and resources, with permissions explicitly defined. Loading that policy into Conjur creates a capability system which allows access to capabilities (like the ability to fetch the database password) based on identity. For any request, Conjur will authenticate the user’s identity then authorize the request according to the policy.

Because Alice has read access on the passwords, Conjur will show them as part of searches and lists of resources she can see. When she goes to fetch the password values, Conjur will check her execute permission to ensure she’s authorized. Likewise, it checks her update permission to authorize her to rotate the passwords.

3. Delegating authority

Alice doesn’t work alone. Her colleague Bob is a developer who needs production access to her database, but he doesn’t need to rotate passwords or access the admin account. She can update her policy to give him appropriate access according to the principle of least authority.

---
# Roles
- !user alice
- !user bob

# Resources
- !variable database-password
- !variable database-admin-password

# Permissions
- !permit
  role: !user alice
  privileges:
    - read
    - execute
    - update
  resources:
    - !variable database-password
    - !variable database-admin-password

- !permit
  role: !user bob
  privileges:
    - read
    - execute
  resource: !variable database-password

What changed: we added a new user and a second permit.

4. Machine identities

In a security review with Alice, Bob relates that he never actually uses the database password himself. Instead, it’s his app that’s logging in to the database to run queries. He has a deploy key for the app and he’d like to store that in Conjur as well. Alice recommends that he use a machine identity for his code instead of sharing his human credentials. They revise the policy to reflect their new understanding:

---
# Roles
- !user alice
- !user bob

## Bob's Query Runner App
- !host query-runner

# Resources
- !variable database-password
- !variable database-admin-password
- !variable query-runner-deploy-key

# Permissions
- !permit
  role: !user alice
  privileges:
    - read
    - execute
    - update
  resources:
    - !variable database-password
    - !variable database-admin-password

- !permit
  role: !user bob
  privileges:
    - read
    - execute
    - update
  resource: !variable query-runner-deploy-key

- !permit
  role: !host query-runner
  privileges:
    - read
    - execute
  resource: !variable database-password

What changed: we added a new host and a new variable. We gave Bob’s privileges on the database-password resource to the query-runner role, and gave Bob permission to fetch and rotate his deploy key.

5. Scaling to larger human organizations

Bob and Alice recognize that the secrets they’re storing in Conjur are useful for other people in their organizations, and it would be nice to use MAML policy to describe the entire infrastructure.

In planning for this expansion, they observe that it would be tedious to maintain the security policy if they had to review and update it every time someone joins, leaves, or changes roles within the organization.

Conjur resolves the tedium with layers, groups, and entitlements. By creating layers (of hosts) and groups (of layers, users, and other groups) and giving permissions to those roles, instead of to users and hosts directly, you can easily modify a person’s permissions by changing their group memberships.

Alice proposes this policy change, in order to prepare to roll Conjur out to a larger user base:

---
# Roles
- !user alice
- !user bob

## Bob's Query Runner App
- !host query-runner

# Groups and layers
- !group database-admins
- !layer database-users
- !group deployers

# Resources
- !variable database-password
- !variable database-admin-password
- !variable query-runner-deploy-key

# Permissions
- !permit
  role: !group database-admins
  privileges:
    - read
    - execute
    - update
  resources:
    - !variable database-password
    - !variable database-admin-password

- !permit
  role: !group deployers
  privileges:
    - read
    - execute
    - update
  resource: !variable query-runner-deploy-key

- !permit
  role: !layer database-users
  privileges:
    - read
    - execute
  resource: !variable database-password

# Entitlements
- !grant
  role: !group database-admins
  member: !user alice

- !grant
  role: !group deployers
  member: !user bob

- !grant
  role: !layer database-users
  member: !host query-runner

What changed: we added three new roles: the database-admins and deployers groups, and the database-users layer. The permits now give permission to a group or layer, rather than directly to a user or host. Finally, we added the “Entitlements” section at the bottom.

When circumstances change in the organization, none of the permits need to be updated or reviewed. The workflow requires only that a new user or host be created and granted membership in the appropriate groups or layers, or that a role have its memberships revoked, as called for by the situation.

Conjur provides tools to make entitlement workflows easier. For example, you can add users to your system by synchronizing with an LDAP or Active Directory server, and you can add hosts to your system in an automated fashion using the host factory.

Delegating even more authority

As adoption of Conjur continues, Alice is administrating policies for an ever increasing number of teams and needs to delegate authority to security operations representatives for each team. Conjur supports this with policy branches. The root of the policy tree can contain any number of branches owned by roles other than the Conjur admin, and those branches can have other branches in turn with further delegation of authority.

Alice restructures her policy using a branch for her database and another branch for the query runner. Alice’s colleague Charlie, another security engineer, will be responsible for vetting and administrating the query runner policy, so its ownership is delegated to him, while Alice remains the owner of the policy for her database.

# Roles
- !user alice
- !user bob
- !user charlie

# Policy branches for database and query runner
- !policy
  id: database
  owner: !user alice
  body:
    # Database roles
    - !layer users
    - !group admins
    # Database resources (variables)
    - !variable password
    - !variable admin-password
    # Database permissions
    - !permit
      role: !group admins
      privileges:
        - read
        - execute
        - update
      resources:
        - !variable password
        - !variable admin-password
    - !permit
      role: !group users
      privileges:
        - read
        - execute
      resources:
        - !variable password

- !policy
  id: query-runner
  owner: !user charlie
  body:
    # Roles
    - !group deployers
    - !host
    # Resources
    - !variable deploy-key
    # Permissions
    - !permit
      role: !group deployers
      privileges:
        - read
        - execute
        - update
      resource: !variable deploy-key

# Entitlements
- !grant
  role: !group database/admins
  members:
    - !user alice
    - !user charlie

- !grant
  role: !group query-runner/deployers
  member: !user bob

- !grant
  role: !layer database/users
  member: !host query-runner

What changed: the database-users and database-admins groups moved into the branch called database, so they got new names: database/users and database/admins. The database-password became database/password for the same reason, and likewise with database-admin-password. The same applies to the roles and resources which now belong to the query-runner policy branch. We added a new user, Charlie. Whereas before, Alice was the sole Conjur administrator who could change policies, she has now delegated control of the query-runner branch to Charlie. He has the ability to change and update this policy branch, but not anything outside of it.

Breaking up the policy into branches has the benefit that Alice can give “update” permission on the policy resource to another person on the security team.

From a single user to an entire policy tree, Conjur MAML makes it easy to model your infrastructure, grant access, and maintain control, all using code that’s human readable and machine enforceable.

Futher Reading

For more on the operational details of using MAML policies with Conjur, you can read the full Conjur Policy documentation. We also have some policy tutorials for you to follow to get started writing and using your own policies. If you’re brand new to Conjur, you can get started with our online learning platform.