access-control icon indicating copy to clipboard operation
access-control copied to clipboard

Better way to accept null values

Open SylvainEstevez opened this issue 7 years ago • 3 comments

We currently use the AWS way of handling null values in permission conditions (see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_Null).

While this provides the expected functionality, it forces the consumers to duplicate their permissions in cases where null is one of the accepted values in addition to another type.

{
    id: 'WithString',
    condition: {
        stringEquals: {
            simpleValue: { foo: 'bar' }
        }
    }
}


{
    id: 'WithNull',
    condition: {
        null: {
            simpleValue: { foo: 'true' }
        }
    }
}

Instead, we would like to find a more elegant solution that would consumers to express the previous 2 conditions as a single "string OR null" statement.

SylvainEstevez avatar Sep 21 '18 09:09 SylvainEstevez

Hello @SylvainEstevez — just wondering if you settled on a path to doing this? Thank you!

lazharichir avatar Apr 28 '20 23:04 lazharichir

Hey @lazharichir, thanks for reaching out. No plan to support "OR" statements at the moment. If you have a syntax proposal, I'd be happy to look at it! But my guess is that it's going to complexify the syntax a lot :/

As a workaround, here is a quick and dirty factory you could get inspiration from in order to avoid code duplication:

import { TPermission, Keys, PermissionEffect } from "@bluejay/access-control";
import { cloneDeep, merge } from 'lodash';

/**
 *
 *
 * @param permission
 * @param conditionPath
 */
const makePropertyNullable = (permission: TPermission, conditionPath: string): TPermission => {
  // Get the property name.
  const nullableProperty = conditionPath.split('.')[2];

  // Create a cloned version of the permission without the target property.
  const filteredPermission = Keys.filter(cloneDeep(permission), `!condition.${conditionPath}`) as TPermission;

  // Finally add the nullable condition.
  return merge(filteredPermission, <Pick<TPermission, 'id' | 'condition'>>{
    id: `${permission.id}_WithNullable_${nullableProperty}`, // `id` needs to be unique.
    condition: {
      null: {
        simpleValue: {
          [nullableProperty]: 'true'
        }
      }
    }
  });
}


const original: TPermission = {
  id: 'FooBar',
  effect: PermissionEffect.ALLOW,
  resource: 'foo',
  action: 'bar',
  condition: {
    stringEquals: {
      simpleValue: {
        aProperty: 'aValue'
      }
    }
  }
};


const withNullableProperty = makePropertyNullable(original, 'stringEquals.simpleValue.aProperty');

Which produces:

{
  "id": "FooBar_WithNullable_aProperty",
  "effect": "allow",
  "resource": "foo",
  "action": "bar",
  "condition": {
    "null": {
      "simpleValue": {
        "aProperty": "true"
      }
    }
  }
}

Hope that helps!

SylvainEstevez avatar Apr 29 '20 07:04 SylvainEstevez

Makes sense, the workaround looks great. Thank you for the help!

On Wed, 29 Apr 2020, 08:47 Sylvain Estevez, [email protected] wrote:

Hey @lazharichir https://github.com/lazharichir, thanks for reaching out. No plan to support "OR" statements at the moment. If you have a syntax proposal, I'd be happy to look at it! But my guess is that it's going to complexify the syntax a lot :/

As a workaround, here is a quick and dirty factory you could get inspiration from in order to avoid code duplication:

import { TPermission, Keys, PermissionEffect } from "@bluejay/access-control";import { cloneDeep, merge } from 'lodash'; /** * * * @param permission * @param conditionPath */const makePropertyNullable = (permission: TPermission, conditionPath: string): TPermission => { // Get the property name. const nullableProperty = conditionPath.split('.')[2];

// Create a cloned version of the permission without the target property. const filteredPermission = Keys.filter(cloneDeep(permission), !condition.${conditionPath}) as TPermission;

// Finally add the nullable condition. return merge(filteredPermission, <Pick<TPermission, 'id' | 'condition'>>{ id: ${permission.id}_WithNullable_${nullableProperty}, // id needs to be unique. condition: { null: { simpleValue: { [nullableProperty]: 'true' } } } }); }

const original: TPermission = { id: 'FooBar', effect: PermissionEffect.ALLOW, resource: 'foo', action: 'bar', condition: { stringEquals: { simpleValue: { aProperty: 'aValue' } } } };

const withNullableProperty = makePropertyNullable(original, 'stringEquals.simpleValue.aProperty');

Which produces:

{ "id": "FooBar_WithNullable_aProperty", "effect": "allow", "resource": "foo", "action": "bar", "condition": { "null": { "simpleValue": { "aProperty": "true" } } } }

Hope that helps!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bluebirds-blue-jay/access-control/issues/10#issuecomment-621043785, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC5GITCGRSKGWKB3D2CCJQ3RO7LPPANCNFSM4FWPJYYA .

lazharichir avatar Apr 29 '20 08:04 lazharichir