Develop Migration-Friendly Policies

Migration is defined as moving policies and their dependencies from one  to another. Migrating content between Gateways is not trivial. Organizations have different deployments, processes, and needs for what migrations must do. This variability makes it a challenge to adhere to predefined guidelines, patterns, and practices. This article describes best practices for developing policies that make migration easier and avoids complications.
gateway84
Migration is defined as moving policies and their dependencies from one 
API Gateway
 to another. Migrating content between Gateways is not trivial. Organizations have different deployments, processes, and needs for what migrations must do. This variability makes it a challenge to adhere to predefined guidelines, patterns, and practices. This article describes best practices for developing policies that make migration easier and avoids complications.
3
Prerequisites
  • Familiarity with the Gateway policy language. The Thinking in Policy section provides a comprehensive primer on Gateway design and auditing, and complex policy logic.
GMU is Policy-Centric 
GMU is a highly flexible, policy-centric migration tool. Unlike backing up and restoring a full Gateway, GMU targets policies and their dependencies. You can export and import all or selected parts of a Gateway and target operations to a specific folder. And all policies can be migrated by targeting the root folder. But GMU can also migrate content that policies do not reference (such as listen ports) and reference points (such as message queues and database connections).
Best Practices for Migrations
Use the following best practices to design policies that make migration easier and avoids complications.
Treat policies as code and give them similar attention
Just like code, policies are part of the policy development life cycle. This life cycle involves propagating policy changes through environments the different phases of projects (for example, between Development and Test). 
Develop policies with a deliberate consideration for migration
The 
API Gateway
 policy language does not heavily constrain how you define policies. There are multiple ways to implement the same logic and behavior. So good policy design is not always obvious. For policy migration, adopt a design approach that makes migration easy.
Use cluster properties to reference environment-specific dependencies
A common design principle in software development is separation of concerns. This principle is about separating a program into distinct sections to address separate concerns. In policy development, a best practice is to separate out environment-specific content. For example, Gateways contain environment-specific values like web and MySQL servers. Environment-specific values are a pressure point to migrations because you cannot move this content between Gateway deployments without manual intervention. Ideally, a policy should not contain any environment-specific values; it should contain only policy logic and reference Gateway entities as dependencies.
Example
Policies that handle HTTP routing are a common and include environment-specific values. Routing and JDBC query assertions often have references to back-end systems (for example, a web server or a MySQL server). These references have values that include a 
hostname
 and 
port
:
routing_wrong_GMU
routing_wrong_GMU
But what happens when this policy is pushed to a Gateway that references different back-end dependencies (for example, from the DEV environment to the TEST environment)? You would have to modify these dependencies 
in the policy
. To avoid explicit references to 
hostname
 and 
port
 in the policy, you can create two custom cluster-wide properties for these dependencies: 
manager.hostname
 and 
manager.port
.
routing_right_GMU
routing_right_GMU
routing_right_GMU2
routing_right_GMU2
You can then reference the cluster properties in a policy using the 
gateway
 prefix:
routing_right_second_GMU
routing_right_second_GMU
During migration, the two cluster-wide properties are imported as dependencies and are separate from policies. The properties for the policy and dependencies can also be modified separately. In short, the policy should not care about the hostname and port for routing HTTP requests.
Organize Gateway content in functional folders
Normally, Gateway folders provide little functionality beyond visual organization and access control that enables a hierarchy of fragments and services for navigation. Folders do not affect resolution paths and cannot be referenced in any other way. So folders are typically not used, or are disregarded. When migrating content, folders matter. Folders and their subcontents can be targeted in exports and imports, which lets you migrate all or parts of a Gateway. You should use folders deliberately, consistently, and with a purpose. Folders can be used to group fragments and services that relate to each other, and separate the ones that do not. When organizing Gateway content, be mindful of which subsets of content might need to be migrated later. In general, avoid migrating everything for every minor change.
Example
An example of strong folder organization is the 
API Gateway
 OAuth Toolkit (OTK) default policy installation. Because the OTK installer wizard is modular, the installed policies are well organized.
 
OTK_explorer_GMU
OTK_explorer_GMU
  
As shown, the folder structure is compartmentalized with services and fragments that are split into folders by their function. This structure is beneficial from a visual standpoint, but also allows a more targeted migration. For example, if you change the OTK database that requires a query changes, migrating these changes can be accomplished by targeting only the 
SecureZone – Storage
 folder.
Avoid using special characters in folder, policy, and service names
GMU requires escaping characters for folder, policy, and service names. When you add the requirements for OS-level escaping characters for Linux and Windows, the complexity increases. Incorrect escaping increases the likelihood of migration failures because the corollary names cannot be found.
Use policy fragments to reuse and isolate migration-sensitive policy
Policies, like folders, should be split up and structured with a purpose. For example, policy pieces can be taken out of services and referenced as policy fragments—similar to import and or include statements in other programming languages. Using policy fragments is a way to control the size of policies and to implement reuse. For example, instead of repeating the same common authentication steps in multiple services, authentication assertions can be implemented in one place—the fragment. They can also be used to isolate policy that is specific to an environment. For example, all context variables with environment-specific values can be placed in a policy fragment named "Environment Configuration."
Related to policy fragments are encapsulated assertions. Encapsulated assertions effectively behave as cosmetic shells to policy fragments and exist in a one-to-one relationship with policy fragments.
Example
In the following service, the request first is authenticated. Then, depending on conditional logic on a request parameter, a message is routed to a back-end service.
policy_wrong_GMU
policy_wrong_GMU
 
Authentication mechanisms are often repeated throughout multiple service within the API defined in service policy. Rather than repeating it in multiple places, it can be isolated as a policy fragment and included by reference instead:
policy_structure_right_GMU
policy_structure_right_GMU
The example also shows a series of context variables (
stockserver.{*}
) that refer to environment-specific values such as hostname and port. You could replace them with cluster-wide properties (as a minimum) or, you could isolate them in a separate policy fragment similar to the authentication snippet. This way, only one policy must be modified whenever the policy set is pushed to a new environment.
Define and enforce an entity-naming strategy
In most cases, you assign names to individual entities (services, folders, JDBC connections, cluster properties, and so on) on the Gateway. Entities should also have a strategy with a well-defined naming pattern and hierarchy. For example, if several cluster properties are needed for information about an authentication back-end system, consider something like: 
backend.auth.host
 and 
backend.auth.port
. The name of the cluster properties makes the purpose obvious. Also, avoid references to environments in entity names whenever possible. It is tempting to use the hostname of the MySQL server to name the associated JDBC connection, but it complicates the migration story. Hostnames can change, but the functional purpose of a server rarely does.
Example
The following example has inconsistent naming of cluster-wide properties:
audit.adminTreshold
 -> "INFO" (
predefined
)
cluster.hostname
 -> "localhost" (
predefined
cluster.httpPort
 -> "8080" (
predefined
dev-env-prefix
 -> "/bulk" (
custom
sslport 
-> "443" (
custom
vm-211.hostname
 -> "vm-211.dev.ca.com" (
custom
)
Inconsistent naming in this example introduces the following issues:
  • The names 
    dev-env-prefix
     and 
    vm-211.hostname
     are environment-specific (to Development), and may not make sense on a Gateway that is targeting a test environment (vm-234.test.ca.com)
The following example uses a more consistent naming scheme:
audit.adminTreshold
 -> "INFO" (
predefined
cluster.hostname
 -> "localhost" (
predefined
cluster.httpPort
 -> "8080" (
predefined
backend.auth.prefix
 -> "/bulk" (
custom
backend.auth.port
 -> "443" (
custom
backend.auth.hostname
 -> "vm-211.dev.ca.com" (
custom
)
Thus, property names remain constant across environments (only the value changes). 
Use secure passwords for policies
We highly recommend that you use secure passwords in policies (via Manage Stored Passwords) rather than use plain text. You can then use the 
migrateOut
 command with the 
--encryptionPassphrase
 argument to secure export passwords in a migration bundle.
Migration in Practice
Content migration is typically done in two steps using export and import:
  1. Export
     writes files to an output directory.
  2. Import
     reads the exported files. 
     
Migration_Friendly_Database
Migration_Friendly_Database
GMU works the same way and never targets two Gateways at once. GMU acts as an intermediary between a single Gateway and the file system. Exporting content involves writing files to an output directory or file and importing content involves reading those already exported files. This file-based design fits the principle of treating policies like code. Containing exports in individual files allows exports to be versioned, maintained, and transferred—just like code.
Example: Migrate All Gateway Folders
A common migration use case is to export a folder and all its children on one Gateway, and import into another Gateway.
migrateOut --folderName migrateIn --destFolder
In the above example, running 
migrateOut
 with the folder argument on the source Gateway produces a file directory structure containing everything that has been targeted and its dependencies. That output is then read when 
migrateIn
 pushes it into the target Gateway. This approach is policy-centric. Because content is moved as files, treat policies like code. By containing exports in individual files, exports can be versioned, maintained, and transferred—just like code.
Example: Templatize Content for Easy Cross-Environment Migration
After policy work is done, a common need is to push the output to different Gateways in multiple environments. For instance, pushing developed policies and their dependencies to a primary and secondary test environment.
However, certain values are likely to change between environments. For example, the hostname of a back-end server in one environment needs to be different in another if the environments are kept entirely separate. If the initial output is pushed to any environment as-is, manual work is required to update all such values. This situation is not ideal and is error prone.
A solution to this is 
templatization
. Templatization strips out all entity values from an export and lists them in one template properties file.
template --bundle --template
When the exported content is imported on the target environment, you specify a template properties file. GMU takes the properties file, and starts a 
detemplatization
 process that moves values the reverse way back from the template properties file to the exported content.
Benefits include:
  • The templatized content is 
    environment independent.
  • Environment-specific values are stored and modified in a single file.
  • Copies of the properties file can be made and modified for different environments.