syntax = "proto2";

import "grr/proto/api/stats.proto";
import "grr/proto/jobs.proto";
import "grr/proto/knowledge_base.proto";
import "grr/proto/semantic.proto";
import "grr/proto/sysinfo.proto";


//
// Entities.
//

// Next id: 20
message ApiClient {
  optional string client_id = 18 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];

  optional string urn = 1 [(sem_type) = {
      type: "ClientURN",
      description: "Client URN."
    }];

  optional ClientInformation agent_info = 2;
  optional HardwareInfo hardware_info = 3;
  optional Uname os_info = 4;
  optional KnowledgeBase knowledge_base = 16;
  optional uint64 memory_size = 17 [(sem_type) = {
      type: "ByteSize",
      description: "Memory available to this client."
    }];

  optional uint64 first_seen_at = 6 [(sem_type) = {
      type: "RDFDatetime",
      description: "When flow was created."
    }];
  optional uint64 last_seen_at = 7 [(sem_type) = {
      type: "RDFDatetime",
      description: "Last time when client checked in."
    }];
  optional uint64 last_booted_at = 8 [(sem_type) = {
      type: "RDFDatetime",
      description: "Last boot time."
    }];
  optional uint64 last_clock = 9 [(sem_type) = {
      type: "RDFDatetime",
      description: "Client clocks value during latest checkin."
    }];
  optional uint64 last_crash_at = 10 [(sem_type) = {
      type: "RDFDatetime",
      description: "Last crash time."
    }];

  repeated AFF4ObjectLabel labels = 11;
  repeated Interface interfaces = 12;
  repeated User users = 13;
  repeated Volume volumes = 14;

  optional uint64 age = 15 [(sem_type) = {
      type: "RDFDatetime",
      description: "Age of the client information."
    }];
  optional CloudInstance cloud_instance = 19;
}

message ApiClientActionRequest {
  optional uint64 task_id = 1;

  optional uint64 task_eta = 2 [(sem_type) = {
      type: "RDFDatetime",
      description: "This task's lease expiration time."
    }];

  optional string session_id = 3 [(sem_type) = {
      type: "RDFURN"
      description: "Session id that triggered the request."
    }];

  optional string client_action = 4 [(sem_type) = {
      description: "Requested client action name."
    }];

  repeated GrrMessage responses = 5 [(sem_type) = {
      description: "Responses queued for this request."
    }];
}

//
// Method arguments and results.
//

message ApiSearchClientsArgs {
  optional string query = 1 [(sem_type) = {
      description: "Search query string. See here for syntax: "
      "https://grr-doc.readthedocs.io/en/v3.2.0/investigating-with-grr/"
      "searching-for-client.html"
  }];
  optional int64 offset = 2 [(sem_type) = {
      description: "Found clients starting offset."
    }];
  optional int64 count = 3 [(sem_type) = {
      description: "Number of found client to fetch."
    }];
}

message ApiSearchClientsResult {
  repeated ApiClient items = 1;
}

message ApiGetClientArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
  optional uint64 timestamp = 2 [(sem_type) = {
      type: "RDFDatetime",
      description: "Timestamp of the client."
    }];
}

message ApiGetClientVersionsArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
  optional uint64 start = 2 [(sem_type) = {
      type: "RDFDatetime",
      description: "Timerange start (timerange is a closed interval)."
    }];
  optional uint64 end = 3 [(sem_type) = {
      type: "RDFDatetime",
      description: "Timerange end (timerange is a closed interval)."
    }];

  enum Mode {
    UNSET = 0; // will default to FULL
    FULL = 1;
    DIFF = 2;
  }
  optional Mode mode = 4 [(sem_type) = {
      description: "Mode to be used: FULL to return full versions for "
      "every timestamp, DIFF to return only differences between subsequent "
      "versions."
    }];
}

message ApiGetClientVersionsResult {
  repeated ApiClient items = 1;
}

message ApiGetClientVersionTimesArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
}

message ApiGetClientVersionTimesResult {
  repeated uint64 times = 1 [(sem_type) = {
      type: "RDFDatetime",
      description: "The list of version times."
    }];
}

message ApiInterrogateClientArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
}

message ApiInterrogateClientResult {
  optional string operation_id = 1 [(sem_type) = {
      description: "The id of the interrogate operation."
    }];
}

message ApiGetInterrogateOperationStateArgs {
  optional string operation_id = 1 [(sem_type) = {
      description: "The id of the interrogate operation."
    }];
}

message ApiGetInterrogateOperationStateResult {
  enum State {
    RUNNING = 0;
    FINISHED = 1;
  }

  optional State state = 1 [(sem_type) = {
      description: "The state of the interrogate operation."
    }];
}

message ApiGetLastClientIPAddressArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
}

message ApiGetLastClientIPAddressResult {
  enum Status {
    UNKNOWN = 0;
    INTERNAL = 1;
    EXTERNAL = 2;
    VPN = 3;
  }

  optional string ip = 1 [(sem_type) = {
      description: "The ip the client used for the latest communication."
    }];
  optional string info = 2 [(sem_type) = {
      description: "Additional info about the ip address."
    }];
  optional Status status = 3 [(sem_type) = {
      description: "The status of the ip address."
    }];
}

message ApiListClientCrashesArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
  optional int64 offset = 2 [(sem_type) = {
      description: "Client crashes starting offset."
    }];
  optional int64 count = 3 [(sem_type) = {
      description: "Max number of crashes to fetch."
    }];
  optional string filter = 4 [(sem_type) = {
      description: "Return only results whose string representation "
      "contains given substring."
    }];
}

message ApiListClientCrashesResult {
  repeated ClientCrash items = 1 [(sem_type) = {
    description: "The client crashes"
  }];
  optional int64 total_count = 2 [(sem_type) = {
    description: "Total count of items."
  }];
}

message ApiAddClientsLabelsArgs {
  repeated string client_ids = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
  repeated string labels = 2;
}

message ApiRemoveClientsLabelsArgs {
  repeated string client_ids = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
  repeated string labels = 2;
}

message ApiListClientsLabelsResult {
  repeated AFF4ObjectLabel items = 1;
}

message ApiListKbFieldsResult {
  repeated string items = 2;
}


message ApiGetClientLoadStatsArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];

  optional uint64 start = 2 [(sem_type) = {
      type: "RDFDatetime",
      description: "Fetch client load stats data starting from this "
      "timestamp. If not set, will default to 30 minutes ago."
    }];
  optional uint64 end = 3 [(sem_type) = {
      type: "RDFDatetime",
      description: "Fetch client load stats data from the interval "
      "ending with this timestamp. If not set, will default to the current "
      "time."
    }];

  enum Metric {
    CPU_PERCENT = 0;
    CPU_SYSTEM = 1;
    CPU_USER = 2;

    IO_READ_BYTES = 3;
    IO_WRITE_BYTES = 4;
    IO_READ_OPS = 5;
    IO_WRITE_OPS = 6;

    NETWORK_BYTES_RECEIVED = 7;
    NETWORK_BYTES_SENT = 8;

    MEMORY_PERCENT = 9;
    MEMORY_RSS_SIZE = 10;
    MEMORY_VMS_SIZE = 11;
  }
  optional Metric metric = 5;
}


message ApiGetClientLoadStatsResult {
  repeated ApiStatsStoreMetricDataPoint data_points = 1;
}

message ApiListClientActionRequestsArgs {
  optional string client_id = 1 [(sem_type) = {
      type: "ApiClientId",
      description: "Client id."
    }];
  optional bool fetch_responses = 2 [(sem_type) = {
      description: "If true, fetch all the responses for every request."
    }];
}

message ApiListClientActionRequestsResult {
  repeated ApiClientActionRequest items = 1;
}
