Feature Flags Policy Governance Tutorial

In this post, we go in depth to teach you all about the Feature Flags’ policy governance: architecture, use cases, data available to utilize, and more.

Last updated
September 23, 2022

Harness Policy as Code, powered by Open Policy Agent (OPA), allows you to write policies as code to automatically govern flag configuration, usage, and process. Policies are applied on every flag creation, toggle, or modification, ensuring your feature flags always stay in a compliant state.

We are proud to be the first feature management solution to support this capability. Global governance policies for feature flags are a big win for engineering organizations that need to enforce standards at scale. They allow for guardrails to be put in place across all releases to ensure standards are met, and they also automate the process, so the developer experience doesn’t change. Developers simply get error messages the way they’re used to during the build and test phase. 

But this post isn’t about why you should do it – it’s about how you do it. In this post, we go in depth and teach you all about the Feature Flags policy governance: architecture, use cases, data available to utilize, and more.

Architecture

Here's a quick overview of how we ensure that your flags always remain in a compliant state, regardless of what changes a user makes or how they decide to make them.  

Feature Flags architecture diagram
  1. A user creates or updates a feature flag. This can be through any of the manners we allow flag changes: UI based, public API, git sync, or a pipeline run. The important point here is that policies are enforced on the backend regardless of how the user tries to make a change so they can’t be circumvented.
  2. Our Feature Flag server calculates the new provisional flag state and sends this to the Harness Policy Engine. This flag data, along with additional info, such as which user made the change and when, as well as other contextual data, is evaluated against your organization's policy set to determine if the change is compliant.
  3. If all policies are successful, the feature flag server will commit the change. If it is non-compliant, the change will be rejected and the user informed of any issues they need to resolve. 

Writing Policies

The Harness Policy Engine is based on OPA, an easy-to-use, extensible solution for creating and enforcing policies across the entire stack. OPA is an open-source project accepted by the Cloud Native Computing Foundation (CNCF) with wide adoption across numerous software delivery use cases. Policies are written in Rego as declarative code, so they are easy to understand and modify — from simple to complex use cases.

You can find more information about writing Rego rules in the official OPA docs

Once you’re ready to get a policy out there, you can write your own and add it to Harness. We also provide some policies out of the box for common use cases, like enforcing naming conventions and ensuring proper promotion of code.

What Data is Available to Write Policies Against?

We know that policies not only relate to the changed entity in question, but can also depend on contextual data, such as who made the change and when. To support these use cases, we provide an ever growing collection of data to the policy engine that you can use when writing your policies. This includes:

  • The full feature flag configuration for the created/updated flag. This includes flag name, description, variations, rules, flag state in every environment you have, and much more.  This is in json format, which matches the format of our public API docs, so if you interact with your flags as code already, it will be very familiar. 
  • Which user made the change, what RBAC permissions they have, and which user groups they belong to.
  • When the change was made. 

Here's a truncated example of the metadata sent to the policy engine

{
"flag": {
"createdAt": 1650618223270,
"defaultOffVariation": "false",
"defaultOnVariation": "true",
"envProperties": [
...environment states and rules go here
],
"identifier": "my_flag",
"kind": "boolean",
"name": "my_flag",
"prerequisites": [],
"project": "my_project",
"variations": [
{
"identifier": "true",
"name": "True",
"value": "true"
},
{
"identifier": "false",
"name": "False",
"value": "false"
}
]
},
"metadata": {
"action": "onsave",
"roleAssignmentMetadata": [
...User RBAC data goes here
],
"timestamp": 1654681128,
"type": "flag",
"user": {
...User account metadata goes here
},
"userGroups": []
}
}

Debugging Policies

Policies are written as code, and as anyone who writes code knows, there will inevitably be lots of edge cases or error scenarios you want to test while refining your policies. Having to create and configure flags in special ways just to test your policies is  frustrating and time consuming. For this reason, we have an integrated policy tester/debugger built right into the UI. 

Feature Flag Tester Debugger UI

Using this debugger, you can go through a standard development process:

  • Develop: Begin by writing your policies in the main text area. Add as many rules and helper functions as you’d like.
  • Test: Using the testing terminal, you can get quick feedback on if the new policies you’re building are having the desired effect. You can hit the “Select Input” button to populate the input field with real flag data from your own project, giving you reliable and realistic test scenarios for your use cases. You can then hit the “Test” button to run the policies and see for the given data input if it would succeed or fail. You can also manually edit this input  data if you’d like to hand craft particular edge cases.
  • Debug: Once your policies are being enforced there may be a time that a user isn’t sure why a change was blocked. This can be a frustrating experience if you’re only provided with a vague error message such as “change forbidden.” Luckily, we provide all the tools for a user to view detailed information on exactly which policies failed, along with the ability to click on these policies and enter this debugger mode, viewing the policy and the exact input their change produced. This will help them verify if it’s a valid rejection or if the policy itself needs to be modified going forward.
Feature Flag policy set evaluations UI

Use Cases

Harness Policy Engine supports a wide array of use cases. These range from simple sanity checks that description fields have been properly completed to complex corporate policies that prevent changes during blackout periods. Feature flag policies broadly fall into these two categories:

Flag Configuration

  • Naming conventions, e.g. flag names must match jira ticket format
  • Mandatory descriptions
  • Only allowing boolean flags to be created (no multivariates)
  • Banning certain functionality e.g. no prerequisite rules allowed
  • Max number of specific target rules

Change Management 

  • Flag cannot be enabled in production unless it is enabled in QA first
  • Flag changes must be made via pipelines with an approval step
  • No changes during certain time periods e.g. when tests are running or during certain mandated blackout periods
  • Flags can’t be enabled by the same user that created it

You can get as creative as you’d like around the rules you need to enforce. We’ve purposely not taken an opinionated UI wizard-based approach on how to create and combine these rules, so you’re free to experiment, start small, and govern what matters to you. 

Where Can I Try It Out?

To learn more about how Harness manages policies, check out our Policies Overview for Feature Flags documentation, or sign up for a free Feature Flags trial today. 

The Modern Software Delivery Platform™

Loved by Developers, Trusted by Businesses
Get Started

Need more info? Contact Sales