Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enum reuse #1214

Open
alanisaac opened this issue Oct 21, 2024 · 4 comments
Open

Enum reuse #1214

alanisaac opened this issue Oct 21, 2024 · 4 comments

Comments

@alanisaac
Copy link
Contributor

alanisaac commented Oct 21, 2024

Background

In OCSF, there are a few standard conventions for enums. Typically:

  • There are two attributes that define an enum, one suffixed with _id that takes on an integer value, and one with no suffix that is typed as a string. The string attribute takes on the value of the caption of the _id field.
  • When the enum id attribute is defined, it uses the enum property to define a set of valid enum values for the attribute. These are defined in-line with each attribute.

There are times where these conventions are broken, but this is the pattern for the majority of enums.

Issue

Because the enums are defined in-line for each attribute in the dictionary, it means that if two attributes have the same enum values (the same conceptual "enum") that set of valid values are defined twice. One example of this duplication is prev_security_level_id and security_level_id define the same enum.

While it doesn't occur with high frequency in the base OCSF schema, I'm writing an extension that has a few more "previous" and "current" fields, and the enum values have useful but long descriptions. Ideally, I could write the enum once as a type, and reuse it in multiple attributes.

  • Does OCSF support enums-as-types out of the box? I haven't seen any examples of it, so I am not sure
    • If it does support this, should it be the convention for enums so duplication is reduced?
    • If it does not support this, is it something that could be enhanced in the framework?

Generally, defining enums as types is common for object-oriented languages, from which OCSF derives a number of other definition conventions (inheritance, profiles (mixins), etc.), so it feels like something that would be in-line with the design philosophy.

@pagbabian-splunk
Copy link
Contributor

pagbabian-splunk commented Oct 21, 2024

Thanks @alanisaac for bringing this up. If I understand you properly, I'm not sure where the duplication would be in the example security_level_id. In this case, the enum is fully defined in the dictionary, as opposed to partially defined (i.e. with just Unknown and Other) in order to have a valid attribute for later reuse. Fully defined attributes in the dictionary imply that the attribute will always have the same values, and in your example, that is the case. Otherwise, a class or object can fill in the other values as they see fit, and the enum can be overloaded (as with type_id for example).

However, I think your point is that the value list is duplicated when the same enum definition is referenced. Would you want the enum as a specific type to not be rendered in the browser more than once? The metaschema definition in this case does not duplicate the value list. Please let me know if I'm missing the point.

@alanisaac
Copy link
Contributor Author

alanisaac commented Oct 21, 2024

If I understand you properly, I'm not sure where the duplication would be in the example security_level_id. In this case, the enum is fully defined in the dictionary, as opposed to partially defined (i.e. with just Unknown and Other) in order to have a valid attribute for later reuse.

The enum is fully defined in the dictionary twice (is duplicated), once on prev_security_level_id and once on security_level_id. Specifically, the two links above contain:

https://github.com/ocsf/ocsf-schema/blob/main/dictionary.json#L3416-L3439

    "enum": {
        "0": {
          "caption": "Unknown"
        },
        "1": {
          "caption": "Secure"
        },
        "2": {
          "caption": "At Risk"
        },
        "3": {
          "caption": "Compromised"
        },
        "99": {
          "caption": "Other",
          "description": "The security level is not mapped. See the <code>prev_security_level</code> attribute, which contains data source specific values."
        }
      }

https://github.com/ocsf/ocsf-schema/blob/main/dictionary.json#L4096-L4112

    "enum": {
        "0": {
          "caption": "Unknown"
        },
        "1": {
          "caption": "Secure"
        },
        "2": {
          "caption": "At Risk"
        },
        "3": {
          "caption": "Compromised"
        },
        "99": {
          "caption": "Other",
          "description": "The security level is not mapped. See the <code>prev_security_level</code> attribute, which contains data source specific values."
        }
      }

If new enum values for a security level were created I suspect we would need to update them in both places. This is rare currently in OCSF, but I am writing an extension that has several more cases of this.

Would you want the enum as a specific type to not be rendered in the browser more than once?

Not at all! I'm not proposing any changes to the way enums are rendered in the browser.

Instead, one alternative solution to this problem could be that enums could be defined in the dictionary.json's types section as their own type. Consider, for example:

The enum defined once under types (as security_level_enum_t):

"types": {
  ...
  "attributes": {
    "security_level_enum_t": {
      "type": "integer_t",
      "enum": {
        "0": {
          "caption": "Unknown"
        },
        "1": {
          "caption": "Secure"
        },
        "2": {
          "caption": "At Risk"
        },
        "3": {
          "caption": "Compromised"
        },
        "99": {
          "caption": "Other",
          "description": "The security level is not mapped. See the sibling attribute, which contains data source specific values."
        }
      }
    },
  }
}

Then the enum type could be referenced in attributes (still in the dictionary, in this case):

"prev_security_level_id": {
      "caption": "Previous Security Level ID",
      "description": "The previous security level of the entity",
      "sibling": "prev_security_level",
      "type": "security_level_enum_t",
},
...
"security_level_id": {
      "caption": "Security Level ID",
      "description": "The security level of the entity",
      "sibling": "security_level",
      "type": "security_level_enum_t",
},

I am waving a magic wand here and assuming the server could be coded to render the same thing it does today, just with this alternative definition.

@pagbabian-splunk
Copy link
Contributor

Ah, of course! Yes this would be a nice improvement. I will add to today's discussion.

@alanisaac
Copy link
Contributor Author

alanisaac commented Oct 22, 2024

As discussed in the working group call on 2024-10-22, OCSF used to have a pattern where enums were defined in a specific folder. It sounds like this was challenging because it was often inconsistent: some enums were defined this way, but others were defined in-line. This still happens, but perhaps less often since switching away from this system.

I wonder if the "types"-based proposal might be a better way of reducing duplication without impacting consistency as much? At least with "types" the enums would still be defined in the dictionary, just in a different section.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants