oasis-tcs/openc2-ap-er

Passing a command to an endpoint when the Target field is already populated

MartinEvandt opened this issue · 7 comments

As mentioned in issue #30, we need a way for the AP to say things like "delete this file on this endpoint".
In this example the ER AP uses the Action "delete" paired with the Target "file", leaving us without a way to refer to the target endpoint that the actuator is to execute the Command on.

The problem stems primarily from the fact that the endpoint itself is not an actuator. However in order for e.g., a file to be deleted from a machine, there has to be something on the endpoint which performs the deletion. This varies from vendor to vendor, and it's difficult to find technical write-ups or good source describing the actual mechanics, but boils down to some sort of process or service running with elevated privileges that receives and executes a command from the EDR server.

I have also yet seen an EDR API which even mentions this program/service. All of them use some sort of unique ID tied to the endpoint itself to specify the target endpoint.

With all that in mind, here are two suggestions on how we can implement this in the AP:

Suggestion 1: Refer to the endpoint in the actuator specifiers map

ID Name Type # Description
1 hostname Hostname 1 The hostname of a machine with ER Actuator capabilities. MUST be formatted as an internet host name as specified in [RFC1123]
2 endpoint_id string 0..1 Unique identifier for a particular device against which the Actuator is to execute a Command.

Sample command

{
  "action": "delete",
  "target":{
    "file": {
       "hashes":"..."
    }
  },
  "actuator": {
    "edr": {
       "hostname":"edr.organization.tld",
       "endpoint_id":"Host123ABC"
    }
  }
}

Suggestion 2: Refer to the endpoint using a Command Argument.

Type: Actuator-target (Map{1..*})

ID Name Type # Description
1 endpoint_id string 0..1 Unique identifier for a particular device on which the Actuator is to execute a Command

An added benefit here would be that we can denote which Commands this argument can be paired with in the Command Arguments matrix.

Table 2.3-2. Command Arguments Matrix

response_requested [...] Actuator-target
contain device valid [...]
contain file valid [...] valid
restart process valid [...] valid

[...]

Sample command

{
  "action": "delete",
  "target":{
    "file": {
       "hashes":"..."
    }
  },
  "args": {
    "edr": {
      "actuator_target":{
        "endpoint_id":"Host123ABC"
      }
    }
   },
  "actuator": {
    "edr": {
       "hostname":"edr.organization.tld",
    }
  }
}

Related to oasis-tcs/openc2-oc2arch#39
Related to oasis-tcs/openc2-transf-mqtt#20

The Message layer currently defined in Language Spec section 3.2 should probably be moved to the Architecture spec. But the Language Spec defines the fields of a command, it must be clear that "Actuator Profile" is a function, not a device, and the "actuator" field of a command identifies a profile, not a device.

The consumer(s) to whom a command is addressed go in the "to" field of a message. It could be a hostname for http transfer or a topic for pub/sub (mqtt) transfer.

Once a command is received by one or more consumers, they decide what to do with it: process it if they support the function in the "actuator" field, or ignore it otherwise. If the consumer supports the edr function but the command has no "actuator" field, the consumer attempts to execute the command as if the actuator field said edr.

This example could be (from LS):

{
  "headers": {
    "request_id": "95ad511c-3339-4111-9c47-9156c47d37d3",
    "created": 1595268027000,
    "from": "Producer1@example.com",
    "to": ["edr.organization.tld"]
  },
  "body": {
    "openc2": {
      "request": {
        "action": "contain",
        "target":{
          "file": {
            "hashes":"..."
          }
        },
        "args": {
          "edr": {
            "actuator_target":{
              "endpoint_id":"Host123ABC"
            }
          }
        },
        "actuator": {
          "edr": {}
        }
      }
    }
  }
}

@dlemire60, I like your term "downstream target" from ap-pac #6.

I think it lends itself well to an argument, which I'm increasingly in favor of implementing this functionality as. This is especially since it lets us specify which commands either supports or MUST include a downstream target in order to be consumed: commands like "contain file" are specifically meant to be targeted at a single endpoint.

So something like this:


Type: Downstream-target (Map{1..*})

ID Name Type # Description
1 endpoint string 0..1 Unique identifier for the downstream endpoint on which the command is to be executed.

Command Arguments Matrix

response_requested [...] downstream_target
contain device valid [...]
contain file valid [...] valid
restart process valid [...] valid
[...]
{
  "action": "delete",
  "target":{
    "file": {
       "hashes":"..."
    }
  },
  "args": {
    "edr": {
      "downstream_target":{
        "endpoint":"Host123ABC"
      }
    }
   },
  "actuator": {
    "edr": {
       "hostname":"edr.organization.tld",
    }
  }
}

I agree that args is the cleanest place to specify downstream devices. How about something like:

  "args": {
    "er": {
      "endpoints": {
        "names": ["Host123ABC", "Host123DEF"],
        "groups": ["group1", "group2"],
        "selector": "some pattern expression"
      }
    }
  }

If a command included no endpoints arg, the OC would perform the command for all endpoints under its control.

As above, the Orchestrator Consumer address "edr.organization.tld" has to go in the message "To" address, otherwise the OC will never receive the command.

Heres a summary for today's ad-hoc meeting:

Summary of the issue

  • Need a way to specify downstream consumers
    • "Perform this Action, on this Target, on this endpoint, managed by this tenant, hosted on this EDR server"
  • Need to nest downstream consumers
  • Nested downstream consumers MUST include order of consumption (actuator -> tenant -> endpoint)
    • Could be defined by using the Record data type from the LS?:
      • An ordered map from a list of keys with positions to values with positionally-defined semantics. Each key has a position and name, and is mapped to a type. Represents a row in a spreadsheet or database table.

  • Certain commands SHOULD/MUST NOT have a downstream consumer specified, this must be reflected in the AP
    • 'contain device' already has all necessary fields specified (given no tenant)
    • Can use the command arguments matrix if downstream consumers are defined in an argument

Example argument:

  "args": {
    "er": {
      "downstream_consumers": {
        "tenant": "some tenant specifier",
        "endpoints": {
          "names": ["Host123ABC", "Host123DEF"],
          "groups": ["group1", "group2"],
          "selector": "some pattern expression"
      }
    }
  }
}

Notes from the meeting:

Issues discussed

Suggested Solutions

  • If an intermediary device Consumes an OpenC2 message it is an Actuator, and should be defined in the Actuator Specifiers
  • Ways of defining which devices included in the Actuator Specifiers are intermediaries (order of consumption):
    • Describing it in writing in the relevant sections of an AP
    • Using an Array from the Language Specification data types, where each index contains a Specifier Type which is handled in order of appearance
  • Suggested creating a separate downstream device/consumer part of the OpenC2 message was mentioned
    • Creating a separate downstream device/consume would require changes to the LS, may be unnecessary and bloat the messages
  • Using the Target fields to specify intermediaries/downstreams, with the execution details defined in the arguments
  • Using the name downstream_device across the various AP's where this problem is relevant
  • Once the AP's have implemented their versions of downstream devices and/or intermediary Actuators, potential additions or changes to the LS can be discussed
    • E.g., Creating Types/defining where to put downstream/intermediary devices in the Language Specification

Actions

  • The name downstream_device was decided on
  • A draft for a downstream_device Command Argument will be in a PR for discussion in the next working meeting
  • Create issues on the LS/OC2Arch GitHub pages to further discuss the issues with editors of other AP's

Other notes

  • AP-ER: The tenant is ultimately an Actuator (a instance of an EDR management server) which consumes OpenC2 messages, only defined more granularly than in on-prem solutions due to being hosted in the cloud
    • Therefore is not considered an intermediary
    • Therefore belongs in the Actuator Specifiers
  • AP-ER: The endpoint is where a Command is to be executed, and OpenC2 message consumption is agnostic: it is where the Action/Target pair is going to be performed, but execution is left to the actuator
    • Therefore does not belong in the Actuator Specifiers
  • AP-ER: ER Command Arguments always applies to how a Command is to be executed in the context of an endpoint

Actions

  • Scrub Architecture Spec, Language Spec and profiles for language equating "actuator" with "device". The LS v1.1 glossary is normative and defines actuator to be a function category, i.e., the name of a profile, which agrees with AS Section 1.3.1 but conflicts with AS Section 2.1. We should note the conflict in LS v1.1 and change the Command property names to be {action, target, args, profile} in the next major version (v2.0). Since the AS hasn't been published we should make the change now and note that the LS will be fixed in v2.

When defining new 1.1 commands we should mentally translate the "actuator" property to "profile". With profile being "document that defines the operations performed by the consumer", profile specifiers is equivalent to "command arguments that apply only to this profile". We should consider if there are any use cases where profile specifiers do not fit in args, and if there are none, simplify the command by eliminating profile specifiers.

Notes from the meeting:

Issues discussed

Suggested Solutions

  • If an intermediary device Consumes an OpenC2 message it is an Actuator, and should be defined in the Actuator Specifiers

It is an "actuator" but as we discussed in the last meeting and also @davaya mentions right below, from an "OpenC2 language" perspective the semantics are different, meaning the actuator refers to a profile and the specifiers to something pertinent to the profile.

So we need to go with defining a ´downstream device´ concept that will fit into the arguments segment of the command. One aspect/constraint to take into consideration is the need for this concept in more actuator profiles. A more representative definition should be incorporated at the LS level.