Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Policy Template Factory #2714

Draft
wants to merge 42 commits into
base: master
Choose a base branch
from
Draft

Policy Template Factory #2714

wants to merge 42 commits into from

Conversation

jvanderhoof
Copy link
Contributor

@jvanderhoof jvanderhoof commented Feb 7, 2023

This work is an extension of the my Hackathon effort from this past fall, which aimed enable an API for generating a variety of Conjur resources.

This effort:

  • Moves policy rendering into Conjur, which allows the Factory templates to be more tightly managed
  • Uses JSON Schema to define required and optional parameters, and validates incoming requests
  • Adds a tool for validating Policy template rendering, to aid in development

Overview

Factory Structure

Factories are stored in Conjur Variables as Base64 encoded values. The above examples are all stored in the conjur/factories/core policy. Shortly, we'll add conjur/factories/authenticators to encapsulate authenticator creation.

The API selects the desired policy (ex. core or authenticators) as well as the target variable name (group, policy, user, managed-policy, etc), we have an immense amount of flexibility to organize and create factories in the future.

Using JSON Schema, each factory defines the inputs it requires and and optionally accepts. This information is available through the factory's info endpoint. This allows us to dynamically include these endpoints in CLIs and SDKs in the future.

Security

Factory endpoint requests require execute permission on the Factory variable and appropriate permssion on the target Policy. This allows Conjur RBAC to be used to manage who/what can use Factories to extend policy, and all actions are captured in Conjur Audit.

Demo

To install the base policies required for the Policy Factory, run the following command on Conjur (Conjur needs to be running):

CONJUR_AUTHN_API_KEY=<admin-api-key> rake policy_factory:load

The above command will install a base policy into the conjur/factories namespace. This base policy includes factories for creating Conjur (all in the core namespace):

  • Group
  • ManagedPolicy - creates a policy with an owner group
  • Policy
  • User

With the above factory templates, the following API endpoints become available:

API Overview

  • Group Endpoint Information

    GET /factory/cucumber/core/group/info
    

    Response:

    { 
      "title": "Group Template",
      "description": "Creates a Conjur Group",
      "type": "object",
      "properties": {
        "id": {
          "description": "Group ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this group into",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the group",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }
  • Create Group

    POST /factory/cucumber/core/group
    

    Accepts a JSON object with the following params:

    Field Required Description
    id True Group ID
    branch True Policy branch to load this group into
    annotations False Additional annotations to add to the group
    {
      "id": "foo-bar",
      "branch": "foo/bar/baz",
      "annotations": {
        "test": "task",
        "authn/k8s": "value"
      }
    }

    The above will commit the following into the foo/bar/baz namespace:

    - !group
      id: foo-bar
      annotations:
        test: task
        authn/k8s: value

    The above API was created from the following schema:

    { 
      "title": "Group Template",
      "description": "Creates a Conjur Group",
      "type": "object",
      "properties": {
        "id": {
          "description": "Group ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this group into",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the group",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }

    and uses the following policy template:

    - !group
      id: <%= id %>
      <% if defined?(annotations) %>
      annotations:
      <% annotations.each do |key, value| -%>
        <%= key %>: <%= value %>
      <% end -%>
      <% end -%>
  • Managed Policy Endpoint Information

    GET /factory/cucumber/core/managed-policy/info
    

    Response:

    { 
      "title": "Group Template",
      "description": "Creates a Conjur Group",
      "type": "object",
      "properties": {
        "id": {
          "description": "Group ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this group into",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the group",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }
  • Create Managed Policy

    This endpoint creates a policy with a corresponding owner group.

    POST /factory/cucumber/core/managed-policy
    

    Accepts a JSON object with the following params:

    Field Required Description
    name True Policy name (used to create the policy ID and the -admins owner group)
    branch True Policy branch to load this policy into
    annotations False Additional annotations to add to the policy
    {
      "id": "foo-bar",
      "branch": "foo/bar/baz",
      "annotations": {
        "test": "task",
        "authn/k8s": "value"
      }
    }

    The above will commit the following into the foo/bar/baz namespace:

    - !group foo-bar-admin
    - !policy
      id: foo-bar
      owner: !group foo-bar-admin
      annotations:
        test: task
        authn/k8s: value

    The above API was created from the following schema:

    { 
      "title": "Managed Policy Template",
      "description": "Policy with an owner group",
      "type": "object",
      "properties": {
        "name": {
          "description": "Policy name (used to create the policy ID and the <name>-admins owner group)",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this policy into",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the user",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }

    and uses the following policy template:

    - !group <%= name %>-admins
    - !policy
      id: <%= name %>
      owner: !group <%= name %>-admins
      <% if defined?(annotations) %>
      annotations:
      <% annotations.each do |key, value| -%>
        <%= key %>: <%= value %>
      <% end -%>
      <% end -%>
  • Policy Endpoint Information

    GET /factory/cucumber/core/policy/info
    

    Response:

    { 
      "title": "User Template",
      "description": "Creates a Conjur Policy",
      "type": "object",
      "properties": {
        "id": {
          "description": "Policy ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this policy into",
          "type": "string"
        },
        "owner": {
          "description": "Optional owner of this policy",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the user",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }
  • Create Policy

    POST /factory/cucumber/core/policy
    

    Accepts a JSON object with the following params:

    Field Required Description
    id True Policy ID
    branch True Policy branch to load this policy into
    owner False Optional owner of this policy
    annotations False Additional annotations to add to the policy
    {
      "id": "foo-bar",
      "branch": "foo/bar/baz",
      "owner": "!group foo-bar"
      "annotations": {
        "test": "task",
        "authn/k8s": "value"
      }
    }

    The above will commit the following policy into the foo/bar/baz namespace, owned by the Conjur group foo-bar:

    - !group
      id: foo-bar
      owner: !group foo-bar
      annotations:
        test: task
        authn/k8s: value

    The above API was created from the following schema:

    { 
      "title": "User Template",
      "description": "Creates a Conjur Policy",
      "type": "object",
      "properties": {
        "id": {
          "description": "Policy ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this policy into",
          "type": "string"
        },
        "owner": {
          "description": "Optional owner of this policy",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the user",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }

    and uses the following policy template:

    - !policy
      id: <%= id %>
      <% if defined?(owner) %>
      owner: <%= owner %>
      <% end %>
      <% if defined?(annotations) %>
      annotations:
      <% annotations.each do |key, value| -%>
        <%= key %>: <%= value %>
      <% end -%>
      <% end -%>
  • User Endpoint Information

    GET /factory/cucumber/core/user/info
    

    Response:

    { 
      "title": "User Template",
      "description": "Creates a Conjur User",
      "type": "object",
      "properties": {
        "id": {
          "description": "User ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this user into",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the user",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }
  • Create User

    POST /factory/cucumber/core/user
    

    Accepts a JSON object with the following params:

    Field Required Description
    id True User ID
    branch True Policy branch to load this user into
    annotations False Additional annotations to add to the user
    {
      "id": "foo-bar",
      "branch": "foo/bar/baz",
      "annotations": {
        "test": "task",
        "authn/k8s": "value"
      }
    }

    The above will commit the following into the foo/bar/baz namespace:

    - !user
      id: foo-bar
      annotations:
        test: task
        authn/k8s: value

    The above API was created from the following schema:

    { 
      "title": "User Template",
      "description": "Creates a Conjur User",
      "type": "object",
      "properties": {
        "id": {
          "description": "User ID",
          "type": "string"
        },
        "branch": {
          "description": "Policy branch to load this user into",
          "type": "string"
        },
        "annotations": {
          "description": "Additional annotations to add to the user",
          "type": "object"
        }
      },
      "required": ["id", "branch"]
    }

    and uses the following policy template:

    - !user
      id: <%= id %>
      <% if defined?(annotations) %>
      annotations:
      <% annotations.each do |key, value| -%>
        <%= key %>: <%= value %>
      <% end -%>
      <% end -%>

Connected Issue/Story

N/A

Definition of Done

At least 1 todo must be completed in the sections below for the PR to be
merged.

Changelog

  • The CHANGELOG has been updated, or
  • This PR does not include user-facing changes and doesn't require a
    CHANGELOG update

Test coverage

  • This PR includes new unit and integration tests to go with the code
    changes, or
  • The changes in this PR do not require tests

Documentation

  • Docs (e.g. READMEs) were updated in this PR
  • A follow-up issue to update official docs has been filed here: [insert issue ID]
  • This PR does not require updating any documentation

Behavior

  • This PR changes product behavior and has been reviewed by a PO, or
  • These changes are part of a larger initiative that will be reviewed later, or
  • No behavior was changed with this PR

Security

  • Security architect has reviewed the changes in this PR,
  • These changes are part of a larger initiative with a separate security review, or
  • There are no security aspects to these changes

jvanderhoof and others added 23 commits April 13, 2023 08:39
- Renamed `Factory` namespace to `Factories`
- Refactored retrieval into a Repository
This ensures we detect the issue in which a http
proxy is not correctly used with kube exec to
inject the Conjur client certificate.
This commit:
  - Adds support for regional STS endpoints.
  - Improves log messaging for failed requests.
  - Adds unit tests for all authenticator functionality.
Conjur is currently the only project which uses the conjur-rack gem. This PR brings it into Conjur to simplify
the authorization process.
This commit:
- Replaces a call to `git` with the equivalent Ruby call. This prevents a Git permission error.
- Addresses all Rubocop warnings.
Failure caused by regex update in #2792
john-odonnell and others added 13 commits July 5, 2023 09:05
Includes RSpec unit tests for these cases, along with VCR cassettes
to playback authentic Identity responses.
 - Spawn multiple processes to execute cucumber tests in parallel. Each process contains it's own indipendent conjur instance and postgresql database to avoid colisions.
 - Dynamically alter Ruby ENV variables based on the process executing the cucumber feature tests.
 - Dockerfile has been altered to support replicated services for parallel tests (this has not been altered to be dynamic and consists of static changes).
 - Alter cucumber.yml profiles to support parallel_tests ruby gem cmd usage

The following tests have not been parallelized:
 - authenticators_k8s
 - rspec tests
  - updates to policy
  - filter empty request params
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants