Skip to main content

Environment Files

It is Bravura Security's recommended best practice to have three environments set up when deploying Bravura Security Fabric: development , QA/UAT/Test and production . These environments often require different values for many components, such as a specific targets, addresses, security groups, userclass-criteria, and so on. Instead of altering data components so they have different values in each of these environments, the product components framework provides the ability to define environment files that contain the environment-specific configuration information for components. These environment .json files are stored within the <instance>\environments directory and are applied to the product instance using the command prompt prior to a relevant component installation.

As an example, target addresses and external database entries are environment-specific configurations that can be defined within environment files and applied during component installations. For a development environment, this would input the target addresses used in development directly into the product during component installation and add external database configuration entries to relevant policy tables.

Business requirement and solution

During an implementation, components are created or modified to contain all of the configuration information for the product. This greatly speeds up the installation and configuration processes needed during an implementation. It also ensures configurations are not missed between development, QA, test, and production environments.

For example, a target system will have an address different in the development environment than the one in production, even if they essentially represent the same integration. Without environment files, we would need to create separate data components for the same target in each environment, to account for these configuration discrepancies. This would make component sets challenging to keep track of, and any common configuration changes made in one environment’s component set would then need to be propagated to all other environment component sets. Tracking configuration changes that need to be applied to individual or all environment component sets becomes difficult to manage and would involve complicated change control procedures.

Environment files provide a solution to install components with the environment-specific configuration values (like target addresses, user class group membership criteria, extdb values, and so on). The specific configuration values applied depend on the environment file (development, QA, test, UAT, production) selected through the manage_components.py command before installing the components.

When to make an environment file

When an implementor determines that configuration settings must be specified during product installation, they first determine if a component containing those configuration settings exists within the <instance>/component/Default components. As a general rule, if a component does not exist, it is exported as a data component and used in the <instance>/component/Custom/ directory. If the component does exist in /Default/ components, it can be overwritten in the environment file(s) or via creating a "Custom" version of the "Default" component.

For /Default/Functional/ components, use the following guidelines to determine whether to customize the component or use an environment file::

  • only Data changes are required (.json or .csv), they go in an environment file.

  • changes to (py, ps) code are needed, they are made in the /Custom/ component.

  • data changes exist, but they are NOT environment-specific, they are made in the /Custom/ component.

It is possible to create the entire instance configuration directly in an environment file, however, for readability and centralization purposes, environment files use templates for component overrides, variables, and other tricks. This allows implementors to change some data, structure or values in one place and apply them elsewhere.

Making an environment file

To create a new environment file:

  1. Navigate to the <instance>\environments folder. If the environments folder does not exist, create it.

  2. Once in the folder, create a new .json file with the name of the company the environment file is being created for followed by the name of the environment the file will be used in.

    In other words, the syntax of the environment file name will be <company>-<environment>.json . For example, an environment file is being created for ABC company for their development environment. The environment file is then called abc-dev.json . This naming scheme is recommended as a way to keep track of which environment file is intended for a particular environment and/or company.

A good starting point for adding content to the new, currently empty, abc-dev.json environment file is to reference the default.json sample file from the <instance>\component\Default\Scenario\hid_env_default directory and copy/paste needed portions from that sample into your abc-dev.json environment file. If you decide to use the full contents of the default.json sample as your new environment file, it is advised that you make a copy of the default.json sample and rename it to the desired environment name. That way, the original default.json sample remains for future reference.

Overriding configuration

Bravura Security Fabric default installation configuration captured in components is overridden by declaring entries in the environment’s .json file.

The base of writing an environment file should be a dictionary with three keys: Scenario, Functional, and Data, so the first thing added to an empty environment file is:

{
	"Scenario": {},
	"Functional": {},
	"Data": {}
}

This structure defines three keys with empty dictionaries corresponding to the three product component types.

Keys not being used can be omitted, but all components can be categorized into these three keys, so it is recommended to leave them in the file if future configurations are added.

From here, the component to be overridden needs to be determined, and the ConfigData entries for that component defined.

Finding configdata component files

For this discussion the Data.hid_target_ad component is used as the desired component to override. The Data.hid_target_ad component is responsible for installing the default Active Directory target with most reference build component installations.

From the component fully qualified name (fqname for short) of Data.hid_target_ad, it is deduced that this override should go under the Data key. So, adding the component name (without the type) to the Data dictionary, gives the environment file entry:

{
	"Scenario": {},
	"Functional": {},
	"Data": {
		"hid_target_ad": {
		}
	}
}

Now the name of the file that the configdata entries exist in for this component needs to be determined. To do so, navigate to the directory of the component in question and open the manifest.xml file. In the manifest file there is a specification for configdata that includes a filename. The name of the file in that section of the manifest file is what you are looking for.

For the Data.hid_target_ad component:

  1. Open the \<instance>\component\default\Data\ directory.

  2. Search through the list of Data components and locate the hid_target_ad component folder.

  3. Inspect the manifest.xml file within the \<instance>\component\Default\Data\hid_target_ad directory.

  4. Its contents contain lines similar to:

    <component>
    	<description>
    		Provides the Active Directory target system configuration
            
    	</description>
    	...
    	<configdata component="Functional.hid_configuration.json_loader.ConfigHook">
    		<filename>ad.json</filename>
    		<priority>50</priority>
    	</configdata>
    </component>

It becomes clear that the ad.json file is the one containing configdata entries due to its placement in the configdata portion of the manifest.

Since only the filename is needed, you may wonder why it's necessary to look in the manifest file. This is because had the ad.json file been nested in a directory, the type of slash (\ or /) indicated in the manifest file matters to the environment file script.

Meaning:

<filename>files/ad.json</filename>

is not the same as:

<filename>files\ad.json</filename>

When writing the environment file override, the same type of slash needs to be specified in the environment file as in the manifest file.

Now that the name of the file is known, adding it to the environment file looks like:

{
	"Scenario": {},
	"Functional": {},
	"Data": {
		"hid_target_ad": {
			"ad.json": {}
		}
	}
}

Past this point, the override syntax in the environment file depends on the type of configuration being overridden. Types of overrides include configuration object (IDMConfig) and policy table (ExtDB) overrides.

IDMConfig override

IDMConfig handles all configuration you would do inside of the product, from things like Account Attribute Definitions, to Target addresses, and System Variables, IDMConfig handles reading the data from a .json file and loading it into the product so it can be leveraged.

To override IDMConfig data, the replacement in the environment file is written similarly to the structure in the .json component file. Building on the Data.hid_target_ad example from before, the agenttime field of our target configuration is accessed by looking through the ad.json file and locating the "agenttime" row of the file.

Opening the ad.json file shows top lines:

"Fields": {
	"address": "{server=demo.local;listNestedGrps=true}",
	"adminclaimhide": true,
	"adminresethide": false,
	"adminunlockhide": false,
	"agenttime": 300,
	...
}

Adding the agenttime field override to the environment file so that the agenttime target configuration option is overridden to 600 uses the syntax:

{
	"Scenario": {},
	"Functional": {},
	"Data": {
		"hid_target_ad": {
			"ad.json": {
				"Fields": {
					"agenttime": 600
				}
			}
		}
	}
}

External data store override

The other common type of configuration to override is data provided from components to External Data Store tables (ExtDB). These are overridden similarly to the IDMConfig data shown before, but with a few slight differences that allow the writer to override specific rows and columns in the csv configuration data that may be included with a particular component.

For this discussion, the steps necessary to override the value for the association_attrs configuration setting in the hid_global_configuration ExtDB policy table are detailed. The default value of association_attrs is employeeNumber and will be overridden in an environment file to be mail instead.

Finding the component

To change the association_attrs row value in the hid_global_configuration ExtDB table, the component we are trying to alter needs to be found. The component for an ExtDB entry can be found by viewing the ComponentOwnerFQN field in the row you are looking to alter.

For the row containing the association_attrs setting, the component name in the ComponentOwnerFQN field is Scenario.im_corp_loaddb.

Finding appropriate CSV rows

Finding the appropriate .csv file that contains the configdata information for the component is a similar process to finding the appropriate .json for IDMConfig overrides.

For the Scenario.im_corp_loaddb component:

  1. Open the \<instance>\component\Default\Scenario directory.

  2. Search through the list of Scenario components and locate the im_corp_loaddb component folder.

  3. Inspect the manifest.xml file within the \<instance>\component\Default\Scenario\im_corp_loaddb directory.

  4. Its contents contain lines similar to:

    <component>
    	<description>
    		Corporate loaddb processing logic.
    	</description>
    	...
    	<configdata component="Functional.hid_global_configuration.model.GlobalConfiguration">
    		<filename>data\global_configuration.csv</filename>
    	</configdata>
    </component>

    It becomes clear that the data\global_configuration.csv file is the one containing configdata entries due to its placement in the configdata portion of the manifest.

  5. Open the \<instance>\component\Default\Scenario\im_corp_loaddb\data\ global_configuration.csv file. The contents show:

    namespace,setting,key,value,description
    LOADDB,skip_list,,,Optional semicolon separated list of targets to skip
    LOADDB,target_list,,,Optional semicolon separated list of targets to use
    LOADDB,association_attrs,,"@shortID,employeeNumber",Add an association
    attribute based on the attributes defined here
    LOADDB,admin_association_attrs,,@shortID,Add an admin association attribute
    based on the attributes defined here

    The third row of the global_configuration.csv is the one containing the default value " @shortID,employeeNumber " we want to override to " @shortID,mail " for the association_attrs setting.

  6. When indicating the third row in the environment file, count rows starting at zero "0". This means that the third row in the .csv corresponds to using the syntax [2]. The environment file then looks like:

    {
    	"Scenario": {
     	  "im_corp_loaddb": {
    		"data\\global_configuration.csv": {
    		  "[2]": {
    			"value": "@shortID,mail"
    		  }
    		}
    	  }
    	},
    	"Functional": {},
    	"Data": {}
    }

Other useful CSV row syntax

Add or exclude rows

Rows can be added or removed from .csv files by adding appropriate syntax to the environment file. This is done by adding a plus + or minus - sign to the row indicator. For example:

{"+[0]":{1,2,3}}

would insert three integers as the first three values in the first row and:

{"-[1]": {}}

would exclude the second row from the indicated .csv file.

Be careful when overriding specific elements in arrays, such as "[0]" (the first element) in the example above. If you use a number out of range, you will get an error at component install that will not mention the environment file. This will make it difficult to trace the source of the error. What you will see is, after an info entry saying the Data component config.json has been loaded, a long Python Traceback that ends in a statement about an item type mismatch.

Replace all values with the same variable in a list

To replace an item for all the rows in a .csv list with the same input, you would use a * row indicator. Here is an example where the "value" item is changed for all rows of the global_configuration.csv file to equal "@shortID,mail" :

{
"Scenario": {
  "im_corp_loaddb": {
    "data\\global_configuration.csv": {
      "[*]": {
        "value": "@shortID,mail"
      }
    }
  }
},
"Functional": {},
"Data": {}
}

Components with two csv files

Components that have multiple .csv files can have numerous files, rows and items altered within the same environment file.

In the example below, the Scenario.pam_vault_management component has one specified row item replaced in the policy_attrval_validation.csv and a different item in two different specified rows replaced within the policy_attrval_calculation.csv file:

{
"Scenario": {
  "pam_vault_management": {
    "data\\policy_attrval_validation.csv": { 
      "[0]": { 
        "set_visible": "True"
      } 
    }, 
    "data\\policy_attrval_calculation.csv": { 
      "[1]": { 
        "SkipRemaining": "Stage" 
      }, 
      "[2]": { 
        "SkipRemaining": "All" 
      } 
    }
  }
},
"Functional": {},
"Data": {}
}

Using an environment file

Environments are managed through the manage_components.py program located in your instance’s \scripts directory. To use the manage_components program:

  1. Open a command prompt as an administrator.

  2. Navigate to your <instance> directory and run the command:

    instance.bat
  3. Navigate to <instance>\scripts to run the manage_components.py program.

Loading an environment file

Environment files must be loaded before the installation of the components it is overriding in order for it to provide the configuration override values. Any components being overridden in the environment file will be installed during the loading of the environment file, along with any of their component dependencies.

To load an environment file, use the command:

manage_components.py env load <environment filename>

Where environment filename corresponds to the name of the .json file in the <instance>\environments directory.

You can only load one environment file at any given time. If an environment file has already been loaded and you try to load it again or try to load a different environment file, you will be presented with an error message akin to, An environment (environment name) is already loaded , and the environment file will fail to load. The reason for this is environments are intended to be applied before configuration starts to enter the system. Changing an environment file and reloading it requires the load to be forced to signify pushing new information, rather than changing incoming data, which is the standard intention of an environment file. This error will also occur if you have mistakenly loaded the wrong environment file and attempt to load the correct one afterwards.

To force the system to load the new environment file add " --force " to your load command:

manage_components.py env load <environment filename> --force

This command will cause Bravura Security Fabric to attempt a reload of any configuration data attached to installed components and make the configuration substitutions your environment file defines.

Note

There have been known issues with certain types of components and the reloading of environment files not working. If a force command does not work contact the Bravura Security support department for advice on how to proceed.

Best practice

Loading environments on a system where components are already installed is risky. If you already have an environment loaded and then try to switch environment files, it could break. There are some components that do not uninstall nicely and these might complain and break upon the new install. It is best practice, and highly recommended, to install environment files before the installation of your first component because of this.

Example: Create environment files to capture idmconfig changes

In this use case, a product implementer for ABC company has set up two product server environments, one for development and one for production. Each environment has a different Active Directory (AD) target address.

The following instructions will walk you through the steps required to create and configure the environment files for both the development (dev) and production (prod) environments. When the environment files are loaded into their respective environments, they will install the component to create the AD target and input the correct address for their environment specific AD system within the target configuration.

Environment details

The Active Directory (AD) target address for each environment is:

  • dev.corp for the dev environment.

  • prod.corp for the prod environment.

Creating the dev and prod environment files

The Data.hid_target_ad component provides a base AD target with a sample targeting address. The Data.hid_target_ad component is called upon and installed as a dependency to many other scenario and functional components.

The sample placeholder AD target address that the Data.hid_target_ad component inputs is server=demo.local;listNestedGrps=true. We know the addresses we want the component to set when installed for both the dev and prod environments, so we need to write the files dictating those addresses. We start by creating two environment files, one for dev and one for prod.

To create the environment files:

  1. Navigate to the \<instance> directory.

  2. If the folder called \<instance>\environments does not currently exist in the instance directory, create it.

  3. Create two files within the newly created environments folder; one called abc-dev.json and the other abc-prod.json.

Identify the component that you want to add the override for

To be able to override configuration data provided by a component, the component you need to override must be identified first. For IDMConfig changes there is no direct way to tell which component is responsible for the configuration information, so there is no definitive way to figure this out. It requires using intuition to guess and then confirm you are correct by searching through the component files. Here are some tips to help identify the component you need to override.

To identify the component:

  • Note the type of object you are trying to override; in this case the aim is to override a target address, so we care about a target component of sorts.

  • If the component is installed as the dependency of a RefBuild component, you can sometimes identify the component by visually inspecting the manifest.xml of the RefBuild or Scenario components.

  • Most product IDMConfig changes will be housed in the Data component directory. In this use case you are looking for a target address IDMConfig change, so a good guess would be that you are looking for a Data component.

  • Most base product Data components follow the naming convention hid_<type>_<identifier> .

Using the pointers noted above, it can be deduced that for overriding the AD target addresses, you should be looking at Data components.

  1. Open the \<instance>\component\default\Data directory.

  2. Searching through the list of Data components you will find a folder called \Data\hid_target_ad . Intuitively this seems like the correct Data component because it includes both "target" and "ad" in the name, but you should verify by inspecting the files.

  3. Inspect the files within the \<instance>\component\Default\Data\hid_target_ad directory. It becomes clear that we’re interested in the ad.json file, as it provides the target address field.

  4. The address field from the ad.json file is the one that provides the default placeholder of server=demo.local;listNestedGrps=true when the component is installed, so we know that the address field is what we have to write the override for in the abc-dev.json and abc-prod.json environment files.

    Now that the data component and specific file we want to provide an override has been determined, the override needs to be specified in our respective environment files for dev and prod. We will start with the abc-dev.json file for the dev environment.

Write the override in the environment files

We have identified the component and field we need to provide an override for and will now specify the override in our respective environments, starting with abc-dev.json.

A good starting point for your environment file is to add three keys, one for each component directory (Data, Functional, Scenario) to help visualize how the overrides apply according to the component's directory. This helps when adding many overrides to environment files since it will keep them organized by component type.

To start the dev environment file:

  1. Open the abc-dev.json file in a plain-text file editor, and add the 3 keys to indicate the component directories by entering the following:

    {
    	"Scenario": {},
    	"Functional": {},
    	"Data": {}
    }
  2. Now that there is a basic skeleton, you know our component of interest is in the Data directory, so add the component name to the Data key. The file now looks like:

    {
    	"Scenario": {},
    	"Functional": {},
    	"Data": {
    		"hid_target_ad": {
    		}
    	}
    }
  3. Next, specify which file from the component is being overridden. It was determined above that file will be the ad.json file. Adding that information makes the environment file look like:

    {
    	"Scenario": {},
    	"Functional": {},
    	"Data": {
    		"hid_target_ad": {
    			"ad.json": {}
    		}
    	}
    }
  4. For the configuration override itself, the right dictionary structure needs to be used to enter into the abc-dev.json environment file to ensure the replacement is applied in the correct location. To do this, navigate to the <instance>\default\Data\hid_target_ad directory and open the ad.json file.

    You will notice that it is a .json file with a dictionary inside. Find the target address field you want to override by inspecting the objects. From the contents of the ad.json file, the "address" is located under "Fields" . The dictionary structure is then ad.json["Fields"]["address"] , so that is what we need to add to the abc-dev.json file.

  5. Navigate back to the abc-dev.json file, open it in the file editor, and add the dictionary structure ad.json["Fields"]["address"] so your file looks like the following:

    {
      "Scenario": {},
      "Functional": {},
      "Data": {
        "hid_target_ad": {
          "ad.json": {
            "Fields": {
              "address": "{server=dev.corp;listNestedGrps=true}"
            }
          }
        }
      }
    }

    From the addition, now abc-dev.json is applying an override to the ad.json file provided by Data.hid_target_ad to change the value of the ["Fields"]["address"] to the dev environment's custom server=dev.corp value.

  6. Save the abc-dev.json file.

  7. Now we can complete a similar change to our abc-prod.json, but using the required value of server=prod.corp for the production environment. Open the abc-prod.json file in the file editor and add the following:

    {
      "Scenario": {},
      "Functional": {},
      "Data": {
        "hid_target_ad": {
          "ad.json": {
            "Fields": {
              "address": "{server=prod.corp;listNestedGrps=true}"
            }
          }
        }
      }
    }
  8. Save the abc-prod.json file.

Load the dev environment

The environment files have been successfully written. In order to apply the configuration overrides from the environment file to the product, the environment file needs to be loaded. To do this for the dev environment:

  1. On your development product server install the product. This is your dev environment.

  2. Create the \environments directory as described above and place the abc-dev.json file into it.

  3. Launch a command prompt as an Administrator and navigate to the \<instance> directory.

  4. Run the command:

    instance.bat

  5. Navigate to the \<instance>\script directory.

  6. Load the environment by running the commands:

    manage_components.py load
    manage_components.py env load abc-dev

Install the Data.hid_target_ad component

It is important to note that you can install the data component individually or as part of the Scenario or Functional component that has it listed as a dependency. Either way, the data component will be installed with the environment file overrides. In this case we will install the data component directly.

  1. While still in the \<instance>\script directory, install the Data.hid_target_ad component by running the command (note: the component is case sensitive):

    manage_components.py install Data.hid_target_ad

    You know that the command has run successfully if the command prompt shows the skins being built and installed.

  2. Verify that your Active Directory target address has now been changed to server=dev.corp;listNestedGrps=true by clicking Manage the system > Resources > Target systems > Manually defined > AD and looking at the value for the Address .

    If the address is changed to server=dev.corp;listNestedGrps=true in the AD target configuration, then you know you have written and applied the environment file correctly.

Example: Create environment files to capture extDB changes

For this use case, a product implementer for XYZ company has set up two product server environments, one for development and one for production. Each environment has different requirements for the method emails are sent, the amount of failed login attempts permitted before user lockout is triggered and the length of the PIN required for multi-factor authentication. These configuration requirements differ from the defaults configured by components.

This configuration example shows how to create dev and prod environment files to capture entry differences within the ExtDB tables for authentication chains and email behavior. Then, it demonstrates how to load the development environment file during an installation on the development environment.

The environment configuration requirements are:

  • Emails should be sent to:

    • FILE only in dev.

    • SMTP only in prod.

  • The number of failed login attempts permitted are:

    • 6 attempts for dev.

    • default attempts for prod (default value is 3).

  • The PIN lengths for multi-factor authentication are:

    • PIN length of 4 for dev.

    • default PIN length for prod (default value is 5).

The following steps need to be completed:

  1. Identify the component needed for the desired external data store override using a test environment with the product installed.

  2. On the test product instance, review the default configurations that the Functional.hid_policy_wfemail component enters into the hid_policy_wfemail policy table.

  3. Create the dev environment file.

  4. Create the prod environment file.

  5. Load the dev environment file on the development environment.

  6. Install the Functional.hid_policy_wfemail component on the development environment.

Requirements

This use case assumes that:

  • A test product instance is available for testing configurations with the Functional.hid_policy_wfemail component installed.

    By default installing the Functional.hid_policy_wfemail component results in emails being sent both to FILE and SMTP server.

  • On a development and production environment, the following is true:

    • Bravura Security Fabric and Bravura Security Connector Pack are installed.

    • An Active Directory target system is added as a source of profiles.

Click below to view a demonstration.

Identify the component that you want to add the override for

A test instance has been setup with a variety of components installed in order to identify the component that configuration changes need to be made to.

Identifying the component for an External data store override is much easier than identifying one for idmconfig changes (in most cases). If you already have an existing instance, you can generally determine which component provides specific rows to a table by looking at the ComponentOwnerFQN field that is included in all external data store tables.

To identify the component:

  1. Log in to Bravura Security Fabric Front-end (PSF) as superuser .

  2. Click Manage External Data Store.

  3. Navigate to the table in question. This might take some guess work until you find the table and rule responsible for the configuration you're trying to alter. For this example, since email settings need to be altered, it’s a good guess to check the hid_policy_wfemail table.

  4. Identify the row you want to override, and note the value of its ComponentOwnerFQN field. For this example, the first rule in this table, where EventID = _DEFAULT_POLICY , shows SendSMTP and WriteFile columns set to True . Scrolling over to the ComponentOwnerFQN field shows it is configured by the Functional.hid_policy_wfemail component. This means the override needs to be applied to the Functional.hid_policy_wfemail component.

Now that we have identified the component to override, the specific component file to override also needs to be determined. For data provided to ExtDB tables, this generally comes from .csv files.

Review default configuration settings for wfemail component

To determine which specific file and fields we need to provide overrides for in the dev environment file:

  1. Navigate to the \<instance>\component\default\functional\hid_policy_wfemail directory.

  2. Open and inspect manifest.xml for configdata entries.

    From the entries, we find the configdata entry shows:

    <configdata component="Functional.hid_policy_wfemail.model.PolicyWFEmail">
    	<filename>data\events.csv</filename>
    </configdata>

    From the placement within configdata entries, it is shown that the file providing configuration information is \data\ events.csv . This information is now used to start building a structure for the dev environment file.

    Note

    The / and \ are not equivalent; the slash in the environment file must match the type used in manifest.xml.

Create the dev environment file

To create the dev environment file, if it does not already exist:

  1. Navigate to your \<instance> directory.

  2. If an \<instance>\environments folder does not currently exist in the instance directory, create one.

  3. Inside the \environments directory, open an appropriate application (like Notepad++ ) to create a new file called xyz-dev.json.

    This will act as the dev environment file. If this file exists already, you only need to add to it.

Override the appropriate CSV rows in the environment file

To write the dev environment file:

  1. Edit the xyz-dev.json file and add the three keys to indicate the component directories by entering the following:

    {
    	"Scenario": {},
    	"Functional": {},
    	"Data": {}
    }
  2. Now that there is a basic skeleton, it is known that the component of interest is in the \Functional directory, so the override is added under the " Functional " key so the file now looks like:

    {
    	"Scenario": {},
    	"Functional": {
    		"hid_policy_wfemail": {}
    	},
    	"Data": {}
    }
  3. The file being overridden from the component now needs to be specified. It was determined above to be \data\ events.csv, so that is added next.

    {
    	"Scenario": {},
    	"Functional": {
    		"hid_policy_wfemail": {
    			"data\\events.csv": {}
    		}
    	},
    	"Data": {}
    }
  4. Writing overrides for .csv files is similar to how overrides are written for .json files, but for .csv files the specific rows being altered need to be identified in the environment file. For this example, the row in the events.csv file where EventID = _DEFAULT_POLICY is being overridden, so the number of this row needs to be recorded in the environment file.

  5. To find the number of the row, open the \<instance>\component\Default\Functional\hid_policy_wfemail\data\ events.csv file and see which line EventID = _DEFAULT_POLICY .

    Viewing the file shows the line with EventID = _DEFAULT_POLICY happens to be the first item in the .csv . To specify the row in the environment file, its index (zero-indexed) needs to be added followed by the fields you want to override for that row. Since EventID = _DEFAULT_POLICY is the first row in the .csv , it has an index of ’0’. The xyz-dev.json environment file then looks like:

    {
    	"Scenario": {},
    	"Functional": {
      	"hid_policy_wfemail": {
    			"data\\events.csv": {
    				"[0]": {
    				}
    			}
    		}
    	},
    	"Data": {}
    }
  6. The Functional.hid_policy_wfemail component by default configures both SendSMTP and WriteFile values to be set to True . Since the development environment is supposed to send emails to file only, the override required is setting the SendSMTP field to FALSE . The environment file override entry in xyz-dev.json then becomes:

    {
    	"Scenario": {},
    	"Functional": {
    		"hid_policy_wfemail": {
    			"data\\events.csv": {
    				"[0]": {
    					"SendSMTP": "FALSE"
    				}
    			}
    		}
    	},
    	"Data": {}
    }

    With this change, when the xyz-dev.json environment is loaded before installing the Functional.hid_policy_wfemail component, the first row of the hid_policy_wfemail policy table is configured with SendSMTP = FALSE . Thus, overriding the default value of SendSMTP = TRUE from the events.csv file.

Create the prod environment file

Create the prod environment file if it does not already exist:

  1. Navigate to your \<instance> directory.

  2. If an \<instance>\environments folder does not currently exist in the instance directory, create one.

  3. Inside the \environments directory, open an appropriate application (like Notepad++ ) to create a new file called xyz-prod.json.

    This will act as our prod environment file. If this file exists already, you only need to add to it.

Override the appropriate CSV rows in the environment file

Following similar steps and logic to the dev environment file, the xyz-prod.json file is written to include an override that ensures email in the prod environment is set to SMTP only and not to file. This means the WriteFile field from the events.csv must be overridden to equal FALSE.

{
	"Scenario": {},
	"Functional": {
		"hid_policy_wfemail": {
			"data\\events.csv": {
				"[0]": {
					"WriteFile": "FALSE"
				}
			}
		}
	},
	"Data": {}
}

Load the dev environment file

This example assumes the development server environment has Bravura Security Fabric installed on the system without the installation of the Functional.hid_policy_wfemail component.

  1. Navigate to the \<instance> directory and create the \ environments directory.

  2. Copy your xyz-dev.json file into that directory.

  3. Launch a command prompt as an Administrator and navigate to the \<instance> directory.

  4. Run the command:

    instance.bat
  5. Navigate to the \<instance>\script directory.

  6. Load the environment file by running the commands:

    manage_components.py load 
    manage_components.py env load xyz-dev

Install Functional.hid_policy_wfemail component

To install the Functional_hid_policy_wfemail component:

  1. While still in the \<instance>\script directory, list the components by running the command (note: the component is case sensitive):

    Manage_components.py install Functional.hid_policy_wfemail

    You know the command has run successfully if the command prompt shows the built and installed skins.

    Additionally, you can check the hid_policy_wfemail ExtDB table entries:

  2. Verify that the SendSMTP value has been configured as FALSE by checking the value in the hid_policy_wfemail EXTdb table:

    1. Log in to Bravura Security Fabric as superuser .

    2. Click Manage External Data Store.

    3. Navigate to the hid_policy_wfemail table.

    4. Review the first rule in the table where EventID = _DEFAULT_POLICY and ensure that the value for SendSMTP = FALSE.

Adding multiple pieces of configuration to an environment file

Since environment files are just .json files, adding more configuration is as simple as adding a comma, and defining another item to override. To display this, we will extend our xyz-dev.json to override the LENGTH and TRIES configurable values provided by the Scenario.hid_authchain_emailpin component to GlobalConfiguration to make the email PIN scenario easier to use in development environments.

For reference, the manifest.xml file for the Scenario.hid_authchain_emailpin component has GlobalConfiguration data provided by the \data\ initial_data.csv file. The default values in the \data\ initial_data.csv file consist of:

  • row 3 with LENGTH = 5

  • row 4 with TRIES = 3

In this example, an override is added to the xyz-dev.json file so that:

  • LENGTH = 4

  • TRIES = 6

Writing the override into the existing xyz-dev.json file appears as:

{
	"Scenario": {
		"hid_authchain_emailpin": {
			"data\\initial_data.csv": {
				"[2]": {
					"value": "4"
				},
				"[3]": {
					"value": "6"
				}
			}
		}
	},
	"Functional": {
		"hid_policy_wfemail": {
			"data\\events.csv": {
				"[0]": {
					"WriteFile": "FALSE"
				}
			}
		}
	},
	"Data": {}
}

Note that just because the override has been added for the component Scenario.hid_authchain_emailpin to the xyz-dev.json environment file, it does not mean an override needs to be added to other environment files. For example, since the default values being provided by the component suit the needs of the production environment, no further entries need to be added to the xyz-prod.json file. The resulting xyz-prod.json file will still appear as:

{
	"Scenario": {},
	"Functional": {
		"hid_policy_wfemail": {
			"data\\events.csv": {
				"[0]": {
					"WriteFile": "FALSE"
				}
			}
		}
	},
	"Data": {}
}

Using Variables

As environment files get larger and contain multiple user classes, target addresses, and so on, it makes sense to define variables at the top of the file to make the process scalable. Using variables for a small set of environment file configurations is unnecessary, such as only having a single target as seen in the configuration example capturing idmconfig changes, but once you have ten or more targets, creating variables is the optimal approach.

Defining variables

Variables are defined in order to replace default configuration values with values intended for multiple environments, such as in a base environment file, or to replace values for specific environments. See Inheriting environments to understand how environment specific files can be written to inherit values from base environment files. Variables are also used to replace the same value multiple times.

To define variables for an environment file, start by declaring them in an entry named _vars . This is usually at the top of the file:

{
"_vars": {
	"ad": {
            "address": "testad.local"
	}
  },

Now that the variable has been defined, it can be accessed in the environment file using: ${_vars.ad.address}

Building on the above example, an AD target address override using the variable would be written as:

{
"_vars": {
	"ad": {
            "address": "testad.local"
	}
  },
"Scenario": {},
"Functional": {},
"Data": {
	"hid_target_ad": {
		"ad.json": {
			"Fields": {      
				"address": "{server=${_vars.ad.address};nameFormat=NT4;}"
			}
		}
	}
  } 
}

Defining multiple variables

A common reason for defining variables in an environment file is unrolling a set of variables to numerous pieces of configuration. For example, multiple target addresses can be defined within variables, and installing the Data.hid_target_ad component can then trigger the creation of multiple AD targets with values pulled from the defined _vars . To do that:

First, define the variables:

{
"_vars": {
	"ad": [
		{
		 "id": "AD",
		 "name": "AD",
		 "address": "{server=testad.local;nameFormat=NT4;}",
		},
     		{
		 "id": "AD2",
		 "name": "AD2",
		 "address": "{server=testad2.local;nameFormat=NT4;}",
		}
	]
  },

Then, define the Data.hid_target_ad component override:

"Scenario": {},
"Functional": {},
"Data": {
	"hid_target_ad": {
		"ad.json": {
			"Fields": {      
				"id": “${_vars.ad.id}",
				"address": “${_vars.ad.address}"
    			}
      	 }
        }
    }
}

In this case, the _vars.ad variable is unrolled from a two-value list into two separate pieces of configuration. When the Data.hid_target_ad component is installed with this configuration, two targets are created: AD and AD2 with their addresses set to their respective values ( {server=testad.local;nameFormat=NT4;} and {server=testad2.local;nameFormat=NT4;} ).

In some situations, you may not want the variable to expand into multiple pieces of configuration. In those cases, the _in_place flag is used in environment files to control the expansion.

Using the _in_place flag

The _in_place flag exists to allow environment files to apply variable expansions in different ways, depending on the requirements of the person developing the environment. The most common place this is encountered is when dealing with IDMConfig data components to manipulate dependent objects inside the .json data files.

The previous section describe variable unrolling and how you can use it to create multiple pieces of configuration from a single set of override instructions using a list of variables. That expansion is equivalent to "_in_place": false because it is generating a separate object for each value in a list, whereas _in_place": true generates a single object, using the last value in a list.

The Dependents and Prerequisites blocks will be handled as if the “_in_place” flag is true by default. Thus, requiring you to define it as false if you need it to be treated differently. For example if you have a list variable that is only being used in the Dependent object and not also the Parent, you need to manually set the Dependent object using the substitution to "_in_place": false in order for the list substitution to generate multiple Dependent objects.

Inheriting environments

A particularly useful use case for environments is inheritance, the ability to define one base environment with many of the overrides in place so environments like: development, production, or stage can easily be set up without needing to repeat entries many times.

One of the most common use cases for this is having different addresses for the AD target depending on the environment you have loaded. For this example company-base.json will be used as the base environment, and both company-dev.json and company-prod.json that inherit from it.

Using a Data.hid_target_ad component override as an example again, the company-base.json file is written as:

{
	"Scenario": {},
	"Functional": {},
	"Data": {
		"hid_target_ad": {
			"ad.json": {
				"Fields": {      
					"address": "{server=${_vars.ad.address};listNestedGrps=true}"
				}
			}
		}
	}
}

Then, other environment files are written similar to this company-dev.json file:

{
	"_inherit" : ["company-base"],
	"_vars": {
		"ad": {
			"address": "development-address.domain"
		}
	}
}

or this company-prod.json :

{
	"_inherit" : ["company-base"],
	"_vars": {
		"ad": {
			"address": "production-address.domain"
		}
	}
}

This would make it so the replacement in the AD target address line depends on which of the two environment files (dev or prod) is loaded, without explicitly overriding the address in both environments. Note that writing your environments like this will make it so company-base.json cannot function independently, which is fine as long as it’s understood in your implementation.