This documentation describes how to use the Hexa Policy Mapper SDK to instantiate and use Hexa Providers to map and provision IDQL to and from target platforms via "providers".
For information on how to develop a new provider, see the Writing A Hexa Provider document.
Hexa Policy Mapper supports the ability to retrieve or set policy from web accessible management APIs.
An integration is defined simply as a selected provider type and a credential used to access the API. Depending on the service provider, the information needed may consist of information such as a project identifier, a security key, and other information. For example, the Amazon integration key file looks like:
{
"accessKeyID": "aws-access-key-id",
"secretAccessKey": "aws-secret-access-key",
"region": "aws-region"
}
Hexa CLI
To add an integration in the Hexa CLI, use the add
command.
% hexa add <platform> --file=<integrationfile>
Here an avp integration is added using a credential file (shown above) called awscred.txt:
% hexa
hexa> add avp --file=awscred.txt
Integration of type: avp, alias: uAz successfully defined
Succesfully loaded 1 policy application(s) from uAz
Integration: uAz
================
Type: avp
PAP Alias: shK
ObjectId: K21RFtX...A93DH7z5
Name: arn:aws:verifiedpermissions::7737....1856:policy-store/K21RFtX...A93DH7z5
Description: My Policy App
Service: VerifiedPermissions
hexa>
GoLang
The following example code opens the integration and loads the defined Policy Application Points and prints them out.package main
import (
"encoding/json"
"fmt"
"os"
"github.com/hexa-org/policy-mapper/api/policyprovider"
"github.com/hexa-org/policy-mapper/sdk"
)
func main() {
keybytes, err := os.ReadFile("awscred.txt")
if err != nil {
panic(-1)
}
info := policyprovider.IntegrationInfo{
Name: sdk.ProviderTypeAvp,
Key: keybytes,
}
integration, err := sdk.OpenIntegration(&info)
if err != nil {
fmt.Println("Error opening integration: " + err.Error())
panic(-1)
}
apps, err := integration.GetPolicyApplicationPoints(nil)
if err != nil {
panic(-1)
}
for _, app := range apps {
jsonBytes, _ := json.MarshalIndent(app, "", " ")
fmt.Println(string(jsonBytes))
}
}
Hexa Get Policies invokes the provider to call to the policy application point to obtain the remote policy and translate it into IDQL.
Hexa CLI
To retrieve policies from a PAP, use the get policies
command. Optionally, use the --output flag to direct output to a file rather than the console.
hexa get policies <alias/objectid> [--output=policies.idql]
For example:
hexa> get policies shK
Policies retrieved for shK:
{
"policies": [
{
"Meta": {
"Version": "0.7",
"SourceData": {
"policyType": "STATIC",
"principal": null,
"resource": null
},
"Description": "Hexa demo canary policy",
"Created": "2023-12-26T21:45:53.558204Z",
"Modified": "2023-12-27T22:20:18.592795Z",
"Etag": "20-68c071fc33494d8d27b460fdae42aa1211025c24",
"PolicyId": "KDqUKMRNEg6aEjZ6mz9dJq",
"PapId": "K21RFtX...A93DH7z5",
"ProviderType": "avp"
},
"Subjects": [
"any"
]
,
"Actions": [
"cedar:hexa_avp::Action::ReadAccount",
"cedar:hexa_avp::Action::Transfer",
"cedar:hexa_avp::Action::Deposit",
"cedar:hexa_avp::Action::Withdrawl",
"cedar:hexa_avp::Action::UpdateAccount"
],
"Object": ""
},
{
"Meta": {
"Version": "0.7",
"SourceData": {
"policyType": "TEMPLATE_LINKED",
"principal": {
"EntityId": "[email protected]",
"EntityType": "hexa_avp::User"
},
"resource": {
"EntityId": "1",
"EntityType": "hexa_avp::account"
}
},
"Description": "TestTemplate",
"Created": "2023-11-23T19:18:16.470806Z",
"Modified": "2023-11-23T19:18:16.470806Z",
"Etag": "20-c7411b365c2d202b19d981a11eacf37bed72e52d",
"PolicyId": "UaN2xdjgv1Dhdpuoa3ebRU",
"PapId": "K21RFtX...A93DH7z5",
"ProviderType": "avp"
},
"Subjects": [
"?principal"
]
,
"Actions": [
"cedar:hexa_avp::Action::ReadAccount"
],
"Object": "cedar:?resource"
}
],
"app": "K21RFtX...A93DH7z5"
}
hexa>
Go Lang
Once an integration is opened, the `Integration.GetPolicies` function can be used to retrieve policies as a `hexapolicy.Policies` structure.package main
import (
"encoding/json"
"fmt"
"os"
"github.com/hexa-org/policy-mapper/api/policyprovider"
"github.com/hexa-org/policy-mapper/sdk"
)
func main() {
. . . <open integration> . . .
apps, err := integration.GetPolicyApplicationPoints(nil)
if err != nil {
panic(-1)
}
for _, app := range apps {
fmt.Println("PAP " + app.ObjectID)
policies, err := integration.GetPolicies(app.ObjectID)
if err != nil {
fmt.Println("Error retrieving policies: " + err.Error())
}
jsonBytes, _ := json.MarshalIndent(policies, "", " ")
fmt.Println("IDQL returned:")
fmt.Println(string(jsonBytes))
}
}
Once an integration is defined, Hexa can set policies by taking input IDQL policies, mapping to the target platform and sending to the update API. In some cases (e.g. Amazon AVP), the existing policies are matched (e.g. using meta information or comparison) and the necessary update operations are calculated as part of the update.
Hexa CLI
The Hexa CLI set policies
command is of the form
set policies <alias|objectid> [-d] --file=<idqlpolicies.json>
If the -d
option is set, the console will show the planned differences and ask for confirmation before proceeding. This output is the same
as for the reconcile
command.
hexa> set policies rKO -d --file=policies.json
Ignoring AVP policyid UaN2xdjgv1Dhdpuoa3ebRU. Template updates not currently supported
0: DIF: UPDATE [ACTION]
{
"Meta": {
{
"Meta": {
"Version": "0.7",
"SourceData": {
"policyType": "STATIC",
"principal": null,
"resource": null
},
"Description": "Hexa demo canary policy",
"Created": "2023-12-26T21:45:53.558204Z",
"Modified": "2023-12-27T22:20:18.592795Z",
"Etag": "20-f2ec1edc53e44c07e4d790d8936ade24b27f04eb",
"PolicyId": "KDqUKMRNEg6aEjZ6mz9dJq",
"PapId": "K21...93DH7z5",
"ProviderType": "avp"
},
"Subjects": [
"any"
],
"Actions": [
"cedar:hexa_avp::Action::ReadAccount",
"cedar:hexa_avp::Action::Transfer",
"cedar:hexa_avp::Action::Deposit",
"cedar:hexa_avp::Action::Withdrawl"
],
"Object": ""
}
1: DIF: UNSUPPORTED
{
"Meta": {
"Version": "0.7",
"SourceData": {
"policyType": "TEMPLATE_LINKED",
"principal": {
"EntityId": "[email protected]",
"EntityType": "hexa_avp::User"
},
"resource": {
"EntityId": "1",
"EntityType": "hexa_avp::account"
}
},
"Description": "TestTemplate",
"Created": "2023-11-23T19:18:16.470806Z",
"Modified": "2023-11-23T19:18:16.470806Z",
"Etag": "W/\"20-c7411b365c2d202b19d981a11eacf37bed72e52d\"",
"PolicyId": "UaN2xdjgv1Dhdpuoa3ebRU",
"PapId": "K21...93DH7z5",
"ProviderType": "avp"
},
"Subjects": [
"?principal"
],
"Actions": [
"cedar:hexa_avp::Action::ReadAccount"
],
"Object": "cedar:?resource"
}
Applying 2 policies to rKO
Update policies Y|[n]?
Go Lang
package main
import (
"fmt"
"os"
"github.com/hexa-org/policy-mapper/api/policyprovider"
"github.com/hexa-org/policy-mapper/pkg/hexapolicysupport"
"github.com/hexa-org/policy-mapper/sdk"
)
func main() {
keybytes, err := os.ReadFile("awscred.txt")
if err != nil {
panic(-1)
}
info := policyprovider.IntegrationInfo{
Name: sdk.ProviderTypeAvp,
Key: keybytes,
}
integration, err := sdk.OpenIntegration(&info)
if err != nil {
fmt.Println("Error opening integration: " + err.Error())
panic(-1)
}
hexaPolicies, err := hexapolicysupport.ParsePolicyFile("idqlinput.json")
status, err := integration.SetPolicyInfo("<alias>",hexaPolicies)
}
Hexa-Mapper provides a few utility packages to parse IDQL, GCP Bind, and Amazon Cedar policy languages.
To parse a file or stream of bytes, use the hexapolicysupport.ParsePolicyFile
or hexapolicySupport.ParsePolicies
functions
to return an array of []policySupport.PolicyInfo
objects. The parser will except either a JSON array of policy objects
or an attribute "policies" which is assigned an array of policies. For example:
{
"policies": [
{
"Meta": {
"Version": "0.7"
},
"Actions": [
"cedar:Action::view"
],
"Subjects": [
"User:\"alice\""
],
"Object": "cedar:Photo::VacationPhoto94.jpg"
}
]
}
The follow shows parsing IDQL JSON into []PolicyInfo
objects:
package main
import (
"fmt"
"github.com/hexa-org/policy-mapper/pkg/hexapolicysupport"
)
func main() {
input := "examples/example_idql.json"
idqlPolicies, err := hexapolicysupport.ParsePolicyFile(input)
if (err != nil) {
fmt.Println(err.Error())
}
// ...
}
When mapping to and from a platform, the mapper
will translate attribute names based on a map provided at instantiation. For example username
translates to account.userid
in Google Bind policy.
The when an attribute name map is provided, only attributes listed in the map are translated. All other attribute names are passed unchanged.
Mapping functions support converting GCP Bind policy in JSON format to and from IDQL JSON form. This includes conversion of GCP Common Expression Language (CEL) to IDQL conditions.
Hexa CLI
To map files in the Hexa CLI, use the map to
or map from
commands as follows:
% hexa map to gcp input.idql gcpout.json
% hexa map from gcp gcpin.json output.idql
To map from or to a policy application source, use the PAP object id or local alias in place of a file name:
% hexa map to gcp input.idql <alias|objectid>
% hexa map from gcp <alias|objectid> output.idql
Go Lang
Instantiate the gcpBind mapper (`github.com/hexa-org/policy-mapper/models/formats/gcpBind`)by providing a map of strings which indicates IDQL names to platform names.package main
import (
"github.com/hexa-org/policy-mapper/models/formats/gcpBind"
"github.com/hexa-org/policy-mapper/pkg/hexapolicysupport"
)
func main() {
input := "examples/example_idql.json"
idqlPolicies, err := hexapolicysupport.ParsePolicyFile(input)
if (err != nil) {
fmt.Println(err.Error())
}
// instantiate gcp mapper with attribute translation for username to account.userid
gcpMapper := gcpBind.New(map[string]string{
"username": "account.userid",
})
// obtain the GCP Binding assignments from IDQL
bindAssignments := gcpMapper.MapPoliciesToBindings(idqlPolicies)
// Convert GCP Bind Assignments back into IDQL
idqlPoliciesAgain, err := gcpMapper.MapBindingAssignmentsToPolicy(bindAssignments)
if err != nil {
fmt.Println(err.Error())
}
}
Mapping functions support converting Amazon Cedar policy to and from IDQL JSON form. This includes conversion of Cedar Conditions to IDQL Conditions.
Hexa CLI
To map files in the Hexa CLI, use the map to
or map from
commands as follows:
hexa map to cedar input.idql cedarout.txt
hexa map from cedar cedarin.txt output.idql
To map from or to a policy application source, use the PAP object id or local alias in place of a file name:
hexa map to cedar input.idql <alias|objectid>
hexa map from cedar <alias|objectid> output.idql
Go Lang
To map from a platform (e.g. Cedar), instantiate the cedar mapper by providing an optional attribute name map, and then call the appropriate parser such as `ParseFile` or `ParseCedarBytes`.package main
import (
"fmt"
"github.com/hexa-org/policy-mapper/models/formats/awsCedar"
)
func main() {
cedarMapper := awsCedar.New(map[string]string{})
input := "mycedarpolicy.txt"
idqlPolicies, err := cedarMapper.ParseFile(input)
if err != nil {
panic(-1)
}
// to map back into Cedar
cedarPolicies, err := cedarMapper.MapPoliciesToCedar(idqlPolicies.Policies)
...
}