oasis-tcs / openc2-oc2ls

OASIS OpenC2 TC: GitHub repository used to propose and track changes to the OpenC2 Language Specification as new working draft level revisions are created and the associated CSDs mature
https://github.com/oasis-tcs/openc2-oc2ls
Other
15 stars 19 forks source link

Query for Pairs #350

Open Vasileios-Mavroeidis opened 4 years ago

Vasileios-Mavroeidis commented 4 years ago

Better description (precision) of action-target pairs a consumer supports in a response command is needed. The importance of that reflects when a consumer supports more than 1 actuator profiles.

For example: A query for capability such as:

{
  "action": "query",
  "target": {
    "features": ["pairs"]
  }
}

could have a response:

{
  "status": 200,
  "results": {
    "pairs": {
      "allow": ["ipv6_net", "ipv6_connection"],
      "deny": ["ipv6_net", "ipv6_connection"],
      "query": ["features"],
      "delete": ["slpf:rule_number"],
      "update": ["file"]
    }
  }
}

A consumer that supports more than one profiles and in case they are similar such as SLPF and SFPF would overlap. The results of such a query should be clean and not have duplicates, such as two times ipv4_connection that does not differentiate between actuators. In such situations, deduplication may seem fine but creates different issues in cases where a target has a different meaning between profiles.

For example a command update:file for a firewall should only be able to update configuration and files related to a firewall. A firewall though can be dedicated or software-based such as Linux ip-tables, where there the actuator should be able to modify only specific files in that host and related to ip-tables. The host though (consumer) may support another actuator profile that also includes an action-target pair update:file but for a different function.

The solution to that is to include the AP namespace identifier NSID as a key for each group of pairs.

An example:

{ 
   "status":200,
   "results":{ 
      "pairs":{ 
         "slpf":{ 
            "allow":[ "ipv6_net","ipv6_connection"],
            "deny":["ipv6_net","ipv6_connection"],
            "query":["features"],
            "delete":["slpf:rule_number"],
            "update":["file"]
         },
         "another-profile":{ 
            "update":["file"],
            "query":["features"]
}}}}
jmbrule commented 4 years ago

Vasileios's second approach is perfectly logical to me. The inclusion of the namespace identifier removes any ambiguity, so when the 'update file' command is received, the actuator doesn't have to decide in which context the command needs to be executed.

dlemire60 commented 4 years ago

Relevant Language Spec sections (based on searching for "pairs":

My initial sense is that Vasileios has identified an important issue that should be addressed in the next version of the Language Spec. Similarly I think his proposed solution is reasonable.

davaya commented 4 years ago

It is an important issue. Potential solutions include:

1) Producer queries the Consumer separately for each actuator identified in query-profiles and the response is unchanged.

2) Producer omits the Actuator in the query-pairs command and the response has all Actuators supported by the Consumer as Vasileios shows.

I don't have a preference ...

One nit: 'NSID' is described incorrectly in V1.0 (#348) - a Namespace is a URI that uniquely identifies the profile (the JSON Schema $id: https://json-schema.org/understanding-json-schema/basics.html#declaring-a-unique-identifier), and the NSID is shorthand for that URI, i.e. what XML calls a "prefix" (https://www.w3schools.com/xml/xml_namespaces.asp). The response to query-profiles is (should be in V1.1) a list of Namespaces (URIs). NSIDs appear only in schemas, never in XML/JSON messages.

An object key such as "slpf" or "sfpf" is a Property Name, not an NSID.

Vasileios-Mavroeidis commented 4 years ago

@davaya Thanks for making clear the use of NSID

bberliner commented 4 years ago

One thing to consider is that the proposed response is a breaking change for the v1.0 language specification. The official LS specifies that the keys to the "pairs" object are all "actions", not "profiles". As such, I'm not a fan of the proposed change since it will break existing implementations that are 1.0 compatible (mine).

My implementation currently does support multiple profiles and to make it be 1.0-compliant, I opted to return the union of all possible action/target pairs in my "query/features" response. So, if one profile is named "x-files" and supports only "deny/file" while a different profile is named "x-devices" and supports only "deny/device", then I would return a single field for "deny", like so:

{
  "status": 200,
  "results": {
    "pairs": {
      "deny": ["file", "device"]
    }
  }
}

Note that that is actually an incomplete response for this fabricated example, since my OpenC2 Consumer/Orchestrator clearly supports "query/features" in order to return this response at all! So I would actually return:

{
  "status": 200,
  "results": {
    "pairs": {
      "query": ["features"],
      "deny": ["file", "device"]
    }
  }
}

The 1.0 spec is unclear about how the required "query/features" action should be returned or not in this instance (this is a separate matter)...

I.e., my orchestrator itself (the thing that handles "query/features" and "query/command" and "cancel/command" in my implementation) doesn't really have a "profile" since it just returns things compatible with the Language Spec itself.

So, the question raised in this issue is: How do we return (and possibly even request) the action/target pairs limited to a specific supported profile? This issue is correct that that is not possible in the 1.0 spec, but I'd like to add that capability in a way that doesn't break the 1.0 spec.

One approach might be to leave this "union" interpretation consistent with how I implemented it on the 1.0 spec (so no breaking change), and to add a way to request a specific profile (or a list of specific profiles as an array, say). Dave mentions this option above: "Producer queries the Consumer separately for each actuator identified in query-profiles and the response is unchanged." This could be implemented as an "args" for the "query/features" command, like so:

{
    "action": "query",
    "target": {
        "features": [
            "pairs"
        ]
    },
    "args": {
        "profiles": [
            "x-files",
            "x-devices"
        ]
    }
}

But that doesn't feel right at first glance.

Another approach might be to simply add the per-profile pairs information automatically but to put it in the place that is already reserved for per-profile "results". So, the response for my fictional example would now look like:

{
  "status": 200,
  "results": {
    "pairs": {
      "query": ["features"],
      "deny": ["file", "device"]
    },
    "x-files": {
      "pairs": {
        "deny": [ "file" ]
      }
    },
    "x-devices": {
      "pairs": {
        "deny": [ "device" ]
      }
    }
  }
}

To me, this feels more natural, and fits with the 1.0 way of returning per-profile specific results in the responses.

Thoughts?

sparrell commented 4 years ago

I’d prefer a backwards compatible 1.1 change over a breaking 2.0 change.

iPhone, iTypo, iApologize


From: Brian Berliner notifications@github.com Sent: Tuesday, January 7, 2020 5:47:21 AM To: oasis-tcs/openc2-oc2ls openc2-oc2ls@noreply.github.com Cc: Subscribed subscribed@noreply.github.com Subject: Re: [oasis-tcs/openc2-oc2ls] Query for Pairs (#350)

One thing to consider is that the proposed response is a breaking change for the v1.0 language specification. The official LS specifies that the keys to the "pairs" object are all "actions", not "profiles". As such, I'm not a fan of the proposed change since it will break existing implementations that are 1.0 compatible (mine).

My implementation currently does support multiple profiles and to make it be 1.0-compliant, I opted to return the union of all possible action/target pairs in my "query/features" response. So, if one profile is named "x-files" and supports only "deny/file" while a different profile is named "x-devices" and supports only "deny/device", then I would return a single field for "deny", like so:

{ "status": 200, "results": { "pairs": { "deny": ["file", "device"] } } }

Note that that is actually an incomplete response for this fabricated example, since my OpenC2 Consumer/Orchestrator clearly supports "query/features" in order to return this response at all! So I would actually return:

{ "status": 200, "results": { "pairs": { "query": ["features"], "deny": ["file", "device"] } } }

The 1.0 spec is unclear about how the required "query/features" action should be returned or not in this instance (this is a separate matter)...

I.e., my orchestrator itself (the thing that handles "query/features" and "query/command" and "cancel/command" in my implementation) doesn't really have a "profile" since it just returns things compatible with the Language Spec itself.

So, the question raised in this issue is: How do we return (and possibly even request) the action/target pairs limited to a specific supported profile? This issue is correct that that is not possible in the 1.0 spec, but I'd like to add that capability in a way that doesn't break the 1.0 spec.

One approach might be to leave this "union" interpretation consistent with how I implemented it on the 1.0 spec (so no breaking change), and to add a way to request a specific profile (or a list of specific profiles as an array, say). Dave mentions this option above: "Producer queries the Consumer separately for each actuator identified in query-profiles and the response is unchanged." This could be implemented as an "args" for the "query/features" command, like so:

{ "action": "query", "target": { "features": [ "pairs" ] }, "args": { "profiles": [ "x-files", "x-devices" ] } }

But that doesn't feel right at first glance.

Another approach might be to simply add the per-profile pairs information automatically but to put it in the place that is already reserved for per-profile "results". So, the response for my fictional example would now look like:

{ "status": 200, "results": { "pairs": { "query": ["features"], "deny": ["file", "device"] }, "x-files": { "pairs": { "deny": [ "file" ] } }, "x-devices": { "pairs": { "deny": [ "device" ] } } } }

To me, this feels more natural, and fits with the 1.0 way of returning per-profile specific results in the responses.

Thoughts?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/oasis-tcs/openc2-oc2ls/issues/350?email_source=notifications&email_token=AANEXD4YQZIHUNDHZLYVIB3Q4N4DTA5CNFSM4KCETVDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIGL43I#issuecomment-571260525, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AANEXDYUIVQNGSRXFKP6EW3Q4N4DTANCNFSM4KCETVDA.

Vasileios-Mavroeidis commented 4 years ago

@bberliner The union approach introduces overhead in resource-constrained environments due to the multiple requests/responses we need for getting the pairs of each profile. Your last approach seems reasonable. I do understand that backwards compatibility is preferred, and i also agree with that, but introducing more bits in the wire for something that looks also "messier" is not my best. Please elaborate if i miss something or if you believe that the aforementioned wouldn't really have an impact.

alevere commented 4 years ago

@bberliner I agree with @Vasileios-Mavroeidis that the last approach seems reasonable even if it introduces more bits. That approach is what I would vote for today.

jmbrule commented 4 years ago

This was a great discussion then it went quiet. Can I assume that the union approach that bberliner suggested is acceptable to all?
If so, then let's bring it up at the next LSC and if no objections, we can ask someone to generate the pull request.
Logical?

sparrell commented 4 years ago

I like Dave Kemp’s answer.

iPhone, iTypo, iApologize


From: David Kemp notifications@github.com Sent: Thursday, February 27, 2020 5:48:22 PM To: oasis-tcs/openc2-oc2ls openc2-oc2ls@noreply.github.com Cc: duncan sfractal.com duncan@sfractal.com; Comment comment@noreply.github.com Subject: Re: [oasis-tcs/openc2-oc2ls] Query for Pairs (#350)

The question and proposed answers assume that a "profile" answers the query pairs command, rather than a "Consumer".

For example a command update:file for a firewall should only be able to update configuration and files related to a firewall. A firewall though can be dedicated or software-based such as Linux ip-tables, where there the actuator should be able to modify only specific files in that host and related to ip-tables. The host though (consumer) may support another actuator profile that also includes an action-target pair update:file but for a different function.

I don't believe that is a problem. The actions and targets are deliberately generic so that they can apply to multiple profiles; one would expect that a firewall, a router, a sandbox, a malware scanner would all be able to "update" a "file". What you don't want to happen is for an ip-tables application to try to "update" a malware scanner image.

But isolating the action-target pairs by profile name won't prevent that from happening - the suitability checking has to happen below the level of actions and targets. If you update a malware file on a device that ONLY supports an ip-tables profile, the device still MUST be able to determine that the update isn't suitable and reject it. Query pairs has nothing to do with it.

So my recommendation is to NOT view each profile individually, but instead return the answer as it's defined in v1.0 - at the Consumer level, not the profile level. If the consumer has 4 profiles, query pairs returns all the actions supported for any of those profiles, and all the targets for those actions in any of the profiles.

What problem are we trying to solve with query pairs? If it's giving an inappropriate command to a function on a device, detecting that inappropriateness has to happen below the action-target level.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/oasis-tcs/openc2-oc2ls/issues/350?email_source=notifications&email_token=AANEXD7FK3YVREPHZUVOGW3RFA7LNA5CNFSM4KCETVDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOENGILHA#issuecomment-592217500, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AANEXD4M4HH5YGGFJFRAELDRFA7LNANCNFSM4KCETVDA.

davaya commented 2 years ago

See https://github.com/oasis-tcs/openc2-oc2ls/issues/365 - it agrees with Brian's example, except that the LS does not define a "deny" command, so the top-level pairs response would include only "query": ["features"], not "deny": ["file", "device"]. Thus it is not a union response, it is three individual response sections for: universal commands defined by the LS plus other commands defined by two profiles.

dlemire60 commented 2 years ago

discussed in triage. next version, action @Vasileios-Mavroeidis

there are multiple (4?) issues that raise this or very similar topic

dlemire60 commented 7 months ago

See #365 - it agrees with Brian's example, except that the LS does not define a "deny" command, so the top-level pairs response would include only "query": ["features"], not "deny": ["file", "device"]. Thus it is not a union response, it is three individual response sections for: universal commands defined by the LS plus other commands defined by two profiles.

Phrasing this differently, if we view the LS as also being the "base consumer device profile", the only command in that profile is "query" : ["features"] (clearly there is a deny action). So @davaya is saying (I think) that @bberliner's final example should really be read as (using some verbose labels for clarity):

{
  "status": 200,
  "results": {
    "ls-profile": {             // commands defined in the LS as the base actuator profile
      pairs": {
          "query": ["features"]
      }
    },
    "x-files profile": {        // commands defined in the x-files actuator profile
      "pairs": {
        "deny": [ "file" ]
      }
    },
    "x-devices profile": {      // commands defined in the x-devices actuator profile
      "pairs": {
        "deny": [ "device" ]
      }
    }
  }
}

with the union from non-base profiles of "deny" : ["file", "device"] removed from the LS "profile" portion because it isn't defined there. This seems like a reasonable approach to addressing the initial issue (whether it's a breaking change I'm not sure) but as I read the definition of Response Results in 3.3.2.2, I think it's more of a small crack than an actual break. I think mostly what's needed is to add some words and an example to illustrate how to handle the situation.

An argument could be made that the ls-profile portion of this isn't necessary because it's mandatory under the LS, but I'm not sure there would be any benefit to removing it.