ISC Transform for Machine Account to get multi-valued account attribute

Hi ISC Experts,

We hit a problem when trying to get the values from a multi-valued account attribute for a Machine Account. The requirement is to extract a value from a multi-valued account attribute (in our case, Tags) and it will be used to map to a Machine Identity as the key. We have to extract the value that is with the format “service~{systemID}”, however the account attribute transforms always only return the first element and it will not work for us as the tags are in random order

I saw a few threads here mentioning the AccountAttribute transform and the $identity context, but neither work for us.

AccountAttrbute Transform - only returns the first element from the attribute. Checking if the multivalued attribute contains a certain value is NOT working neither, no matter what it just populates the first item out.

Using $identity context in a rule like $identity.getLinksByAppIdOrName() - no, we don’t have identity in machine account.

Display multiple account id using transform - Identity Security Cloud (ISC) / ISC Discussion and Questions - SailPoint Developer Community

Any ideas? Thanks

Hello Ronald. I would treat this as a limitation of the accountAttribute transform for this use case.

AWS aggregates Tags as a multi-valued string attribute in Key~Value format. In your case, accountAttribute is returning only the first value. accountPropertyFilter filters which account is selected, not which value inside a multi-valued attribute, so it cannot dynamically return the entry starting with service~.

I would use a Transform Rule and read the raw attribute directly:

import java.util.Collection;

Object rawTags = idn.getRawAccountAttribute(
    sourceId,
    nativeIdentity,
    "Tags"
);

if (rawTags instanceof Collection) {
    for (Object value : (Collection) rawTags) {
        if (value != null) {
            String tag = value.toString();
            if (tag.startsWith("service~")) {
                return tag;
                // Or return only systemID:
                // return tag.substring("service~".length());
            }
        }
    }
}

return null;

getRawAccountAttribute() reads the account by source ID + native identity, so it does not require $identity or getLinksByAppIdOrName().

Pass sourceId and nativeIdentity into the Transform Rule as attributes. For nativeIdentity, use the AWS schema attribute configured as the account’s Account ID rather than assuming ARN.

Machine Account mappings support transforms, so use this rule in the Machine Identity mapping and reprocess the classification. A Transform Rule is a cloud rule and must go through SailPoint review/deployment.

Short of a rule, I do not see a documented transform-only way to dynamically return an arbitrary service~* value from the multi-valued Tags attribute. If possible, the cleaner alternative is to expose the service ID as its own single-valued source attribute.

Thanks @punna0001 . It sounds promising.

I have prepared the transform rule but got stuck in rule validator (I only got the v3.0.28 and it did not recognise “Transform” type rule". The page about the rule validator from the rule has been removed (https://community.sailpoint.com/t5/Professional-Services/IdentityNow-Rule-Validator/ta-p/166116), and I have raised a Support ticket for it.

Hope it will work and by then I will mark this as a solution. Thanks

Hello @punna0001, I deployed the Transform Rule and I tested it with some dummy values and tested in Identity Profile Preview and it looks good.

However, it does not work when I apply this rule and the transform in the Machine Account Mapping.

I tried using hardcoded values in the transform or using the accountAttributes for the nativeIdentity value, but neither is working. It just does not render any results on the account. I tested with another simple transform just to extract the value of the nativeIdentity (in our case we used ARN) and it is working.

Here is my sample transform that referenced the Transform Rule

{
	"name": "Test Machine Account Tags",
    "type": "firstValid",
    "attributes": {
        "values": [
			{
				"attributes": {
					"sn": {
						"attributes": {
							"values": [
								{
                                    "attributes": {
                                    "name": "<Transform Rule Name>",
                                    "nativeIdentity": "arn:aws:iam::xxx/yyy/zzz",
                                    "sourceName": "<sourceId>",
                                    "lookupPrefix": "service~",
                                    "sourceAttribute": "Tags"
                                    },
                                    "type": "rule"
								},
								"NoServiceNumber"
							]
						},
						"type": "firstValid"
					},
					"ni": {
						"attributes": {
							"values": [
								{
								  "attributes": {
                                    "sourceName": "<sourceName>",
                                    "attributeName": "ARN"
								  },
								  "type": "accountAttribute"
								},
								"NoNI"
							]
						},
						"type": "firstValid"
					},
					"value": ServiceNumer: $sn, NativeId: $ni"
				},
				"type": "static"
			},
            "Default Tag"
        ]
    },
    "internal": false
}

It does not work neither with nested accountAttribute transform in the Rule transform

{
	"name": "Test Machine Account Tags",
    "type": "firstValid",
    "attributes": {
        "values": [
			{
				"attributes": {
					"sn": {
						"attributes": {
							"values": [
								{
                                    "attributes": {
                                    "name": "<Transform Rule Name>",
                                    "nativeIdentity": {
                                      "attributes": {
                                        "sourceName": "<sourceName>",
                                        "attributeName": "ARN"
                                      },
                                      "type": "accountAttribute"
                                    },
                                    "sourceName": "<sourceId>",
                                    "lookupPrefix": "service~",
                                    "sourceAttribute": "Tags"
                                    },
                                    "type": "rule"
								},
								"NoServiceNumber"
							]
						},
						"type": "firstValid"
					},
					"ni": {
						"attributes": {
							"values": [
								{
								  "attributes": {
                                    "sourceName": "<sourceName>",
                                    "attributeName": "ARN"
								  },
								  "type": "accountAttribute"
								},
								"NoNI"
							]
						},
						"type": "firstValid"
					},
					"value": ServiceNumer: $sn, NativeId: $ni"
				},
				"type": "static"
			},
            "Default Tag"
        ]
    },
    "internal": false
}

Here is the sample Transform rule I used

import java.util.Collection;

String _sourceName = sourceName;
String _nativeIdentity = nativeIdentity;
String _sourceAttribute = sourceAttribute;
String _lookupPrefix = lookupPrefix;

Object rawValues = idn.getRawAccountAttribute(_sourceName, _nativeIdentity, _sourceAttribute);

if (rawValues instanceof Collection) {
    for (Object value : (Collection) rawValues) {
        if (value != null) {
            String tag = value.toString();
            if (tag.startsWith(_lookupPrefix)) {
                return tag.substring(_lookupPrefix.length());
            }
        }
    }
}
	
return null;

Any ideas and comments are appreciated, thanks.

Hello Ronald. Since it also fails with hardcoded values, I would first check whether the Transform Rule is actually running in the Machine Account Mapping path. Try reducing the rule to: return "RULE_OK";

Apply it to the same Machine Account field where a simple transform already works, then reprocess classification. The Machine Account documentation says mappings support transforms, but I could not find anything explicitly confirming Transform Rules in this context. You could also check the saved mapping with:

GET /sources/v1/{sourceId}/machine-account-mappings
X-SailPoint-Experimental: true

If RULE_OK does not appear, I would suspect the rule execution/mapping path rather than getRawAccountAttribute(). If it does work, the next test could be:

return String.valueOf(
    idn.accountExistsByNativeIdentity(sourceId, nativeIdentity)
);

Use the machine account’s actual sourceId and nativeIdentity for this test rather than assuming ARN is the same value. If that returns true, then move back to:

idn.getRawAccountAttribute(sourceId, nativeIdentity, "Tags");

I would also rename sourceName to sourceId in the transform and rule so it matches the current IdnRuleUtil signature.

Hello @punna0001 , thank you for your response.

I have tested the Transform Rule with hardcoded values in Identity Profile and I can get expected results from there, so I believe the rule itself, with provided nativeIdentity and the sourceID and sourceName (I tested both, both are working), is working, at least in Identity Profile.

Like in the samples above, I tried using boththe hardcoded values and the actual values from accountAttribute transform, but neither works. The issue is it does not do anything at all, not even returning the default value from the firstValid transform. That’s why I have a feeling that the Machine Account Mapping may not support the Transform Rule and terminated the entire calculation of the mapping.

I can try to create another dummy Transform Rule that just returns a text and see if the Machine Account Mapping can get the value.

Regarding the signature of IdnRuleUtil (sourceName to sourceId in Transform), as mentioned above, I have tested it in Identity Profile it is working as expected, so I believe the signature and the presentation is right.

Thanks again and I will keep you posted for any updates.

Hello Ronald. Thanks for confirming. Yes, I think the dummy Transform Rule is the right next test. Something as simple as:

return "RULE_OK";

applied to the same Machine Account Mapping field where a normal transform already works should help isolate it.

Since even the outer firstValid fallback is not being returned, I would suspect the rule transform may be erroring or not being evaluated correctly in the Machine Account Mapping path, rather than this being an issue with nativeIdentity or getRawAccountAttribute().

The Machine Account documentation confirms transforms are supported in mappings, but I still cannot find anything explicitly confirming Transform Rules in this context. If the simple rule also produces nothing while a normal transform works on the same field, that would be a good comparison to raise with SailPoint Support.

Please keep us posted on the result.

Hello @punna0001 , created a dummy Transform rule that only returns a text. Again it works perfectly if I map it in Identity Profile with a Rule type transform. However, it does not work in Machine Account Mapping like the previous one. It does not throw error or print anything weird, but it just terminates the calculation of the entire account.

I have opened a support for some time in parallel, hoping to get more insights from them. Thanks again for your suggestions

That comparison is useful. Since the same simple Transform Rule works in Identity Profile but does not return anything in Machine Account Mapping, it strongly points to the Rule transform not being supported or not being evaluated correctly in the Machine Account Mapping path, rather than an issue with your rule logic or nativeIdentity.

Since you already have a Support case open, I think that is the right next step. I would ask them specifically to confirm whether Transform Rules are supported in Machine Account Mapping, and if so, whether this behavior is a known limitation or defect.

Please share what Support confirms. It would be useful to know the supported behavior here.