Understanding access metadata (AMD)

LUSID controls access to data stored in LUSID using data policies.

You can write a data policy that restricts access to a particular entity in LUSID (such as a portfolio, instrument or person) using one of its identifiers.

As an alternative, for some types of entity (see below), you can write a data policy that restricts access using access metadata (AMD) that has been applied to that entity instead. This might make for a more dynamic entitlement system. Rather than relying on hard-coded attributes of real-world concepts that can change over time, you can base restrictions on attributes encoded within AMD that can be dynamically updated without rewriting existing data policies.

For more information on data policies, how they control access to LUSID in conjunction with feature policies, the order in which all your policies are evaluated, and current support for data policy checks, start with this explanatory article.

Current support for AMD

The following types of entity currently support AMD:

We are working to extend support to other types.

How it works

AMD is associated with the identifier of an entity. You can write a data policy that controls access to a particular piece of data through the identifier associated with that AMD.

Note: This is especially useful for entities that support multiple identifiers such as persons. Access can be allowed via one of its identifiers but not other(s).

An AMD object consists of a metadataKey mapped to an array of AccessMetadataValue objects. The JSON schema is as follows:

{
    "type": "object",
    "additionalProperties":
    {
        "type": "array",
        "items":
        {
            "$ref": "#/definitions/AccessMetadataValue"
        }
    },
    "definitions":
    {
        "AccessMetadataValue":
        {
            "required":
            [
                "value"
            ],
            "type": "object",
            "properties":
            {
                "value":
                {
                    "maxLength": 2048,
                    "minLength": 0,
                    "type": "string"
                },
                "provider":
                {
                    "maxLength": 50,
                    "minLength": 0,
                    "type": "string",
                    "nullable": true
                }
            },
            "additionalProperties": false,
            "description": "An access control value. Provider should only be used if you are a service provide licensing data. In that case the provider value must match your domain."
        }
    }
}

For example, this AMD object for a portfolio has a metadataKey of FundGroup that is mapped to the fund groups FG1 and FG2:

{
    "FundGroup":
    [
        {
            "value": "FG1",
            "provider": "InternalSystem"
        },
        {
            "value": "FG2",
            "provider": "InternalSystem"
        }
    ]
}

Applying and maintaining AMD for an entity

The following API endpoints are available for all types of entity that support AMD:

Operation

Description

Example API endpoint for portfolios

Upsert AMD

Associate AMD with the identifier of an entity

UpsertPortfolioAccessMetadata

Patch AMD

Patch AMD associated with the identifier of an entity

PatchPortfolioAccessMetadata

Get all AMD

Get all AMD for an entity

GetPortfolioMetadata

Get AMD by key

Get AMD associated with the identifier of an entity

GetPortfoliosAccessMetadataByKey

Delete AMD

Delete AMD associated with the identifier of an entity

DeleteKeyFromPortfolioAccessMetadata

Note that access control for applying and maintaining AMD can itself be set up separately.

Writing a data policy based on AMD

You can write a data policy based on AMD using metadata selectors (MetadataSelectorDefinition). This is in contrast to a data policy based on identifiers, which use identifier selectors (idSelectorDefinition).

A metadata selector allows for matching based on the AMD associated with an identifier. This matching is defined by one or more metadata expressions. All expressions in the same MetadataSelectorDefinition must match (logical AND) for the data policy to take effect.

The following expression operators can be used in MetadataSelectorDefinition:

Expression operator

Description

equals

Matches if textValue is equal to the AMD. 

notEquals

Matches if textValue is not equal to the AMD.

in

textValue must be a comma-separated list of strings, for example FG1,FG2,FG3. Matches if any of the textValue strings in the list are equal to the AMD.

Metadata selectors only work with AMD. Matching of metadata selectors cannot be done on fields, properties, or other data associated with an entity.

Example 1

The following metadata selector matches when a user is attempting to read a portfolio where the array of AccessMetadataValue objects associated with a metadataKey of FundGroup has at least one value of FG1:

{
    "metadataSelectorDefinition":
    {
        "expressions":
        [
            {
                "metadataKey": "FundGroup",
                "operator": "equals",
                "textValue": "FG1"
            }
        ],
        "actions":
        [
            {
                "scope": "default",
                "activity": "Read",
                "entity": "Portfolio"
            }
        ],
        "name": "matches-FG1-Portfolios",
        "description": "Grants read-only access to portfolios in FG1"
    }
}

Example 2

The following metadata selector matches when a user is attempting to read a portfolio where the array of AccessMetadataValue objects associated with a metadataKey of FundGroup has at least one value of FG1 and at least one other value of FG2:

{
    "metadataSelectorDefinition":
    {
        "expressions":
        [
            {
                "metadataKey": "FundGroup",
                "operator": "equals",
                "textValue": "FG1"
            },
            {
                "metadataKey": "FundGroup",
                "operator": "equals",
                "textValue": "FG2"
            }
        ],
        "actions":
        [
            {
                "scope": "default",
                "activity": "Read",
                "entity": "Portfolio"
            }
        ],
        "name": "matches-FG1-and-FG2-Portfolios",
        "description": "Grants read-only access to portfolios in both FG1 and FG2"
    }
}

Example 3

The following metadata selector matches when a user is attempting to read a portfolio where the array of AccessMetadataValue objects associated with a metadataKey of FundGroup has at least one value of FG1 or FG2:

{
    "metadataSelectorDefinition":
    {
        "expressions":
        [
            {
                "metadataKey": "FundGroup",
                "operator": "in",
                "textValue": "FG1,FG2"
            }
        ],
        "actions":
        [
            {
                "scope": "default",
                "activity": "Read",
                "entity": "Portfolio"
            }
        ],
        "name": "matches-FG1-or-FG2-Portfolios",
        "description": "Grants read-only access to portfolios in both FG1 and FG2"
    }
}