This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Advanced use cases

Examples of advanced use cases when interacting with the Endor Labs REST API.

1 - Using the query service

Learn how to use the Query Service for advanced use cases with the Endor Labs REST API.

In addition to REST API endpoints for individual Resource Kinds, the Endor Labs REST API exposes a generic graph API capability through the Query Service endpoint. This Query Service may be used to retrieve resources and their related resources in a single call.

Requests for resources through the Query Service are sent with a Query that specifies a Resource Kind and optional list parameters to control the data returned from the request for that resource. The Query may also specify nested references, connecting related Resource Kinds, and returning all corresponding data in the response.

List projects with package version counts

The following Query returns the number of package versions in the default branch of each project.

  1. Request a list of projects, but only return the uuid, meta.name and processing_status fields for each project.
  2. Connect the project uuid to the corresponding child package version spec.project_uuid field.
  3. Set additional parameters to filter to only resources from the project’s default branch, and to return the count of resources.©
endorctl api create --resource Query \
  --data '{
    "meta": {
      "name": "Projects with Package Version Counts"
    },
    "spec": {
      "query_spec": {
        "kind": "Project",
        "list_parameters": {
          "mask": "uuid,meta.name,processing_status"
        },
        "references": [
          {
            "connect_from": "uuid",
            "connect_to": "spec.project_uuid",
            "query_spec": {
              "kind": "PackageVersion",
              "list_parameters": {
                "filter": "context.type==CONTEXT_TYPE_MAIN",
                "count": true
              }
            }
          }
        ]
      }
    }
  }'
query_data=$(cat << EOF
{
  "meta": {
    "name": "Projects with Package Version Counts"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "mask": "uuid,meta.name,processing_status"
      },
      "references": [
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "kind": "PackageVersion",
            "list_parameters": {
              "filter": "context.type==CONTEXT_TYPE_MAIN",
              "count": true
            }
          }
        }
      ]
    }
  },
  "tenant_meta": {
    "namespace": "$ENDOR_NAMESPACE"
  }
}
EOF
)

curl "https://api.endorlabs.com/v1/namespaces/$ENDOR_NAMESPACE/queries" \
  --header "Authorization: Bearer $ENDOR_TOKEN" \
  --request POST \
  --data "$query_data"
@baseUrl = https://api.endorlabs.com
@token = <insert-access-token>
@namespace = <insert-namespace>

###
POST {{baseUrl}}/v1/namespaces/{{namespace}}/queries HTTP/1.1
Authorization: Bearer {{token}}

{
  "meta": {
    "name": "Projects with Package Version Counts"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "mask": "uuid,meta.name,processing_status"
      },
      "references": [
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "kind": "PackageVersion",
            "list_parameters": {
              "filter": "context.type==CONTEXT_TYPE_MAIN",
              "count": true
            }
          }
        }
      ]
    }
  },
  "tenant_meta": {
    "namespace": "{{namespace}}"
  }
}

The response for the example above includes the query request that was sent, along with the list response data added under the spec.query_response field.

For each project in the list response, response data for each reference is added under the meta.references field.

{
  "meta": {
    "name": "Projects with Package Version Counts"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "mask": "uuid,meta.name,processing_status"
      }
    },
    "query_response": {
      "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListProjectsResponse",
      "list": {
        "objects": [
          {
            "meta": {
              "name": "https://github.com/example/app.git",
              "references": {
                "PackageVersion": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListPackageVersionsResponse",
                  "count_response": {
                    "count": 12
                  }
                }
              }
            },
            "processing_status": {
              "analytic_time": "2023-10-28T03:41:40.824366382Z",
              "disable_automated_scan": false,
              "scan_state": "SCAN_STATE_IDLE",
              "scan_time": "2024-06-03T17:43:33.994191285Z"
            },
            "uuid": "633cbce48c4eb448a44d717b"
          },
          {
            "meta": {
              "name": "https://github.com/example/go-uuid.git",
              "references": {
                "PackageVersion": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListPackageVersionsResponse",
                  "count_response": {
                    "count": 8
                  }
                }
              }
            },
            "processing_status": {
              "analytic_time": "2023-06-21T02:06:43.081498151Z",
              "disable_automated_scan": false,
              "scan_state": "SCAN_STATE_IDLE",
              "scan_time": "2024-06-03T17:43:47.098976874Z"
            },
            "uuid": "633cbce48c4eb448a44d717e"
          },
          {
            "meta": {
              "name": "https://github.com/example/go-lru.git",
              "references": {
                "PackageVersion": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListPackageVersionsResponse",
                  "count_response": {
                    "count": 28
                  }
                }
              }
            },
            "processing_status": {
              "analytic_time": "2023-06-21T02:08:44.727640782Z",
              "disable_automated_scan": false,
              "scan_state": "SCAN_STATE_IDLE",
              "scan_time": "2024-06-03T17:43:52.028934453Z"
            },
            "uuid": "633cbce48c4eb448a44d7181"
          }
        ],
        "response": {
          "next_page_token": null
        }
      }
    }
  }
}

List projects, with repository versions and CI/CD tool metrics

The following query requests a list of projects, with a reference for the related RepositoryVersion resources for the default branch, and the corresponding CI/CD tool Metric resources.

  1. Request a list of projects, but only return the uuid and meta.name fields for each project.
  2. Connect the project uuid to the corresponding child RepositoryVersion meta.parent_uuid field.
  3. Set additional parameters to filter to only resources from the project’s default branch, and an additional nested reference for Metric objects related to the RepositoryVersions, with a filter to return only Metrics for the CI/CD tools.
endorctl api create --resource Query \
  --data '{
    "meta": {
      "name": "Projects with RepositoryVersions and CI/CD Tool Metrics"
    },
    "spec": {
      "query_spec": {
        "kind": "Project",
        "list_parameters": {
          "mask": "uuid,meta.name"
        },
        "references": [
          {
            "connect_from": "uuid",
            "connect_to": "meta.parent_uuid",
            "query_spec": {
              "kind": "RepositoryVersion",
              "list_parameters": {
                "filter": "context.type==CONTEXT_TYPE_MAIN",
                "mask": "uuid,meta.name,scan_object"
              },
              "references": [
                {
                  "connect_from": "uuid",
                  "connect_to": "meta.parent_uuid",
                  "query_spec": {
                    "kind": "Metric",
                    "list_parameters": {
                      "filter": "spec.analytic==\"version_cicd_tools\""
                    }
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }'
query_data=$(cat << EOF
{
  "meta": {
    "name": "Projects with RepositoryVersions and CI/CD Tool Metrics"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "mask": "uuid,meta.name"
      },
      "references": [
        {
          "connect_from": "uuid",
          "connect_to": "meta.parent_uuid",
          "query_spec": {
            "kind": "RepositoryVersion",
            "list_parameters": {
              "filter": "context.type==CONTEXT_TYPE_MAIN",
              "mask": "uuid,meta.name,scan_object"
            },
            "references": [
              {
                "connect_from": "uuid",
                "connect_to": "meta.parent_uuid",
                "query_spec": {
                  "kind": "Metric",
                  "list_parameters": {
                    "filter": "spec.analytic==\"version_cicd_tools\""
                  }
                }
              }
            ]
          }
        }
      ]
    }
  },
  "tenant_meta": {
    "namespace": "$ENDOR_NAMESPACE"
  }
}
EOF
)

curl "https://api.endorlabs.com/v1/namespaces/$ENDOR_NAMESPACE/queries" \
  --header "Authorization: Bearer $ENDOR_TOKEN" \
  --request POST \
  --data "$query_data"
@baseUrl = https://api.endorlabs.com
@token = <insert-access-token>
@namespace = <insert-namespace>

###
POST {{baseUrl}}/v1/namespaces/{{namespace}}/queries HTTP/1.1
Authorization: Bearer {{token}}

{
  "meta": {
    "name": "Projects with RepositoryVersions and CI/CD Tool Metrics"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "mask": "uuid,meta.name"
      },
      "references": [
        {
          "connect_from": "uuid",
          "connect_to": "meta.parent_uuid",
          "query_spec": {
            "kind": "RepositoryVersion",
            "list_parameters": {
              "filter": "context.type==CONTEXT_TYPE_MAIN",
              "mask": "uuid,meta.name,scan_object"
            },
            "references": [
              {
                "connect_from": "uuid",
                "connect_to": "meta.parent_uuid",
                "query_spec": {
                  "kind": "Metric",
                  "list_parameters": {
                    "filter": "spec.analytic==\"version_cicd_tools\""
                  }
                }
              }
            ]
          }
        }
      ]
    }
  },
  "tenant_meta": {
    "namespace": "{{namespace}}"
  }
}

The response for the example above includes then related repository versions and metrics as nested references under their parent resources.

{
  "meta": {
    "name": "Projects with RepositoryVersions and CI/CD Tool Metrics"
  },
  "spec": {
    "query_response": {
      "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListProjectsResponse",
      "list": {
        "objects": [
          {
            "meta": {
              "name": "https://github.com/OWASP-Benchmark/BenchmarkJava.git",
              "references": {
                "RepositoryVersion": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListRepositoryVersionsResponse",
                  "list": {
                    "objects": [
                      {
                        "meta": {
                          "name": "master",
                          "references": {
                            "Metric": {
                              "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListMetricsResponse",
                              "list": {
                                "objects": [
                                  {
                                    "spec": {
                                      "analytic": "version_cicd_tools",
                                      "metric_values": {
                                        "CiCdTools": {
                                          "category": "CiCdTools",
                                          "ci_cd_tools": {
                                            "tools": [
                                              // additional content from response not shown here
                                            ]
                                          }
                                        }
                                      }
                                    },
                                    "uuid": "65b0287557d245d7a840220d"
                                  }
                                ],
                                "response": {}
                              }
                            }
                          }
                        },
                        "scan_object": {
                          "scan_time": "2024-04-15T02:17:56.541640347Z",
                          "status": "STATUS_SCANNED"
                        },
                        "uuid": "65b02837f82e0aeecbf468df"
                      }
                    ],
                    "response": {}
                  }
                }
              }
            },
            "uuid": "65b028374ab228de2903786e"
          }
        ],
        "response": {}
      }
    },

    // additional content from response not shown here
}

The following query example requests the projects matching the given filter, with multiple references specified for the counts of related finding resources for the default branch.

Note: when using multiple references of the same resource kind, the field return_as is provided as the key to be used in the references of the response.

endorctl api create --resource Query \
  --data '{
    "meta": {
      "name": "Project with Finding counts by category"
    },
    "spec": {
      "query_spec": {
        "kind": "Project",
        "list_parameters": {
          "filter": "meta.name matches \"acme-monorepo\"",
          "mask": "uuid,meta.name"
        },
        "references": [
          {
            "connect_from": "uuid",
            "connect_to": "spec.project_uuid",
            "query_spec": {
              "return_as": "VulnerabilityFindingsCount",
              "kind": "Finding",
              "list_parameters": {
                "count": true,
                "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]"
              }
            }
          },
          {
            "connect_from": "uuid",
            "connect_to": "spec.project_uuid",
            "query_spec": {
              "return_as": "SecretsFindingsCount",
              "kind": "Finding",
              "list_parameters": {
                "count": true,
                "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_SECRETS]"
              }
            }
          },
          {
            "connect_from": "uuid",
            "connect_to": "spec.project_uuid",
            "query_spec": {
              "return_as": "MalwareFindingsCount",
              "kind": "Finding",
              "list_parameters": {
                "count": true,
                "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_MALWARE]"
              }
            }
          }
        ]
      }
    }
  }'
query_data=$(cat << EOF
{
  "meta": {
    "name": "Project with Finding counts by category"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "filter": "meta.name matches \"acme-monorepo\"",
        "mask": "uuid,meta.name"
      },
      "references": [
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "return_as": "VulnerabilityFindingsCount",
            "kind": "Finding",
            "list_parameters": {
              "count": true,
              "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]"
            }
          }
        },
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "return_as": "SecretsFindingsCount",
            "kind": "Finding",
            "list_parameters": {
              "count": true,
              "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_SECRETS]"
            }
          }
        },
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "return_as": "MalwareFindingsCount",
            "kind": "Finding",
            "list_parameters": {
              "count": true,
              "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_MALWARE]"
            }
          }
        }
      ]
    }
  },
  "tenant_meta": {
    "namespace": "$ENDOR_NAMESPACE"
  }
}
EOF
)

curl "https://api.endorlabs.com/v1/namespaces/$ENDOR_NAMESPACE/queries" \
  --header "Authorization: Bearer $ENDOR_TOKEN" \
  --request POST \
  --data "$query_data"
@baseUrl = https://api.endorlabs.com
@token = <insert-access-token>
@namespace = <insert-namespace>

###
POST {{baseUrl}}/v1/namespaces/{{namespace}}/queries HTTP/1.1
Authorization: Bearer {{token}}

{
  "meta": {
    "name": "Project with Finding counts by category"
  },
  "spec": {
    "query_spec": {
      "kind": "Project",
      "list_parameters": {
        "filter": "meta.name matches \"acme-monorepo\"",
        "mask": "uuid,meta.name"
      },
      "references": [
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "return_as": "VulnerabilityFindingsCount",
            "kind": "Finding",
            "list_parameters": {
              "count": true,
              "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]"
            }
          }
        },
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "return_as": "SecretsFindingsCount",
            "kind": "Finding",
            "list_parameters": {
              "count": true,
              "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_SECRETS]"
            }
          }
        },
        {
          "connect_from": "uuid",
          "connect_to": "spec.project_uuid",
          "query_spec": {
            "return_as": "MalwareFindingsCount",
            "kind": "Finding",
            "list_parameters": {
              "count": true,
              "filter": "context.type==CONTEXT_TYPE_MAIN and spec.finding_categories contains [FINDING_CATEGORY_MALWARE]"
            }
          }
        }
      ]
    }
  },
  "tenant_meta": {
    "namespace": "{{namespace}}"
  }
}

The response for the above example includes the Finding counts as references on the project list response, using the values provided with return_as for the reference keys.

{
  "meta": {
    "name": "Project with Finding counts by category"
  },
  "spec": {
    "query_response": {
      "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListProjectsResponse",
      "list": {
        "objects": [
          {
            "meta": {
              "name": "https://github.com/example/acme-monorepo.git",
              "references": {
                "MalwareFindingsCount": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListFindingsResponse",
                  "count_response": {
                    "count": 1
                  }
                },
                "SecretsFindingsCount": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListFindingsResponse",
                  "count_response": {
                    "count": 8
                  }
                },
                "VulnerabilityFindingsCount": {
                  "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListFindingsResponse",
                  "count_response": {
                    "count": 74
                  }
                }
              }
            },
            "uuid": "65bbde52d70a7f64c70de4d6"
          }
        ],
        "response": {}
      }
    },

    // additional content from response not shown here
}

Pagination in Query Service endpoint

The page_size field allows you to control the number of elements returned. By default, this value is 100, with a maximum of 500. A paginated response includes a value for the field, next_page_token. You can use this value to fetch additional pages of results.

For example, the following query requests for vulnerability findings.


endorctl api create --resource Query \
  --data '{
  "tenant_meta": {
    "namespace": "doe"
  },
  "spec": {
    "query_spec": {
      "kind": "Finding",
      "list_parameters": {
        "page_size": 50,
        "filter": "meta.name == \'vulnerability\'"
      }
    }
  }
}'

The response to the request contains next_page_token.

{
  "spec": {
    "query_response": {
      "@type": "type.googleapis.com/internal.endor.ai.endor.v1.ListFindingsResponse",
      "list": {
        "objects": [
          {
            "meta": {
              "name": "vulnerability",
              "description": "Example vulnerability finding"
            },
            "spec": {
              "level": "FINDING_LEVEL_CRITICAL",
              "finding_categories": ["FINDING_CATEGORY_VULNERABILITY"]
            }
          }
          // Additional findings up to page_size of 50
        ],
        "response": {
          "next_page_token": 50,
          "next_page_id": "unique-id-for-next-page"
        }
      }
    }
  }
}

Send the next request with the next_page_token to fetch the next set of results.


endorctl api create --resource Query \
  --data '{
  "tenant_meta": {
    "namespace": "doe"
  },
  "spec": {
    "query_spec": {
      "kind": "Finding",
      "list_parameters": {
        "page_size": 50,
        "page_token": 50,
        "filter": "meta.name == \'vulnerability\'"
      }
    }
  }
}'

2 - Using saved queries

Learn how to use saved queries for interacting with the Endor Labs REST API.

The Endor Labs REST API provides the Query Service for flexible requests for resources. The Endor Labs REST API also provides the ability to save and manage queries for your own use cases through the Saved Query Service.

See Using the Query Service for examples on using the Query Service to specify and request resources from the Endor Labs REST API.

Creating a saved query

To create a saved query, a Query object specifying the request is embedded in a SavedQuery object.

saved_query_data=$(cat << EOF
{
  "meta": {
    "name": "Saved Query for Recent Vulnerabilities"
  },
  "spec": {
    "query": {
      "meta": {
        "name": "Query for Recent Vulnerabilities"
      },
      "spec": {
        "query_spec": {
          "kind": "Finding",
          "list_parameters": {
            "filter": "meta.create_time > now(-24h) and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]",
            "mask": "uuid,meta.create_time,meta.update_time,meta.description,spec.level"
          }
        }
      },
      "tenant_meta": {
        "namespace": "$ENDOR_NAMESPACE"
      }
    }
  }
}
EOF
)

endorctl api create --resource SavedQuery \
  --data "$saved_query_data"
saved_query_data=$(cat << EOF
{
  "meta": {
    "name": "Saved Query for Recent Vulnerabilities"
  },
  "spec": {
    "query": {
      "meta": {
        "name": "Query for Recent Vulnerabilities"
      },
      "spec": {
        "query_spec": {
          "kind": "Finding",
          "list_parameters": {
            "filter": "meta.create_time > now(-24h) and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]",
            "mask": "uuid,meta.create_time,meta.update_time,meta.description,spec.level"
          }
        }
      },
      "tenant_meta": {
        "namespace": "$ENDOR_NAMESPACE"
      }
    }
  },
  "tenant_meta": {
    "namespace": "$ENDOR_NAMESPACE"
  }
}
EOF
)

curl "https://api.endorlabs.com/v1/namespaces/$ENDOR_NAMESPACE/saved-queries" \
  --header "Authorization: Bearer $ENDOR_TOKEN" \
  --request POST \
  --data "$saved_query_data"
@baseUrl = https://api.endorlabs.com
@token = <insert-access-token>
@namespace = <insert-namespace>

###
POST {{baseUrl}}/v1/namespaces/{{namespace}}/saved-queries HTTP/1.1
Authorization: Bearer {{token}}

{
  "meta": {
    "name": "Saved Query for Recent Vulnerabilities"
  },
  "spec": {
    "query": {
      "meta": {
        "name": "Query for Recent Vulnerabilities"
      },
      "spec": {
        "query_spec": {
          "kind": "Finding",
          "list_parameters": {
            "filter": "meta.create_time > now(-24h) and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]",
            "mask": "uuid,meta.create_time,meta.update_time,meta.description,spec.level"
          }
        }
      },
      "tenant_meta": {
        "namespace": "{{namespace}}"
      }
    }
  },
  "tenant_meta": {
    "namespace": "{{namespace}}"
  }
}

Updating a saved query

The following example updates the Query specified in the SavedQuery to add additional list parameters.

saved_query_uuid="<insert-uuid>"
saved_query_data=$(cat << EOF
{
  "spec": {
    "query": {
      "spec": {
        "query_spec": {
          "kind": "Finding",
          "list_parameters": {
            "filter": "meta.create_time > now(-24h) and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]",
            "mask": "uuid,meta.create_time,meta.update_time,meta.description,spec.level",
            "page_size": 10,
            "sort": {
              "order": "SORT_ENTRY_ORDER_DESC",
              "path": "meta.create_time"
            }
          }
        }
      }
    }
  }
}
EOF
)

endorctl api update --resource SavedQuery \
  --uuid "$saved_query_uuid" \
  --field-mask "spec.query.spec.query_spec" \
  --data "$saved_query_data"
saved_query_uuid="<insert-uuid>"
saved_query_data=$(cat << EOF
{
  "request": {
    "update_mask": "spec.query.spec.query_spec"
  },
  "object": {
    "uuid": "$saved_query_uuid",
    "spec": {
      "query": {
        "spec": {
          "query_spec": {
            "kind": "Finding",
            "list_parameters": {
              "filter": "meta.create_time > now(-24h) and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]",
              "mask": "uuid,meta.create_time,meta.update_time,meta.description,spec.level",
              "page_size": 10,
              "sort": {
                "order": "SORT_ENTRY_ORDER_DESC",
                "path": "meta.create_time"
              }
            }
          }
        }
      }
    }
  }
}
EOF
)

curl "https://api.endorlabs.com/v1/namespaces/$ENDOR_NAMESPACE/saved-queries" \
  --header "Authorization: Bearer $ENDOR_TOKEN" \
  --request PATCH \
  --data "$saved_query_data"
@baseUrl = https://api.endorlabs.com
@token = <insert-access-token>
@namespace = <insert-namespace>
@uuid = <insert-uuid>

###
PATCH {{baseUrl}}/v1/namespaces/{{namespace}}/saved-queries HTTP/1.1
Authorization: Bearer {{token}}

{
  "request": {
    "update_mask": "spec.query.spec.query_spec"
  },
  "object": {
    "uuid": "{{uuid}}",
    "spec": {
      "query": {
        "spec": {
          "query_spec": {
            "kind": "Finding",
            "list_parameters": {
              "filter": "meta.create_time > now(-24h) and spec.finding_categories contains [FINDING_CATEGORY_VULNERABILITY]",
              "mask": "uuid,meta.create_time,meta.update_time,meta.description,spec.level",
              "page_size": 10,
              "sort": {
                "order": "SORT_ENTRY_ORDER_DESC",
                "path": "meta.create_time"
              }
            }
          }
        }
      }
    }
  }
}

See also interactive mode for managing updates to a SavedQuery with endorctl api update:

endorctl api update --interactive --resource SavedQuery \
  --name "Saved Query for Recent Vulnerabilities"

Evaluating saved queries

After a Saved Query has been created, the request specified by the Query in the SavedQuery may be evaluated on demand.

endorctl api get --resource SavedQuery --uuid <insert-uuid>
base_url="https://api.endorlabs.com"
uuid="<insert-uuid>"

curl "$base_url/v1/namespaces/$ENDOR_NAMESPACE/saved-queries/$uuid/evaluate" \
  --header "Authorization: Bearer $ENDOR_TOKEN"
@baseUrl = https://api.endorlabs.com
@token = <insert-access-token>
@namespace = <insert-namespace>
@uuid = <insert-uuid>

###
GET {{baseUrl}}/v1/namespaces/{{namespace}}/saved-queries/{{uuid}}/evaluate HTTP/1.1
Authorization: Bearer {{token}}

The resulting data from evaluating the saved query will be returned in the response in a nested field under the Query specification. The jq command may be used to extract the nested data.

For the example queries given above, the following command will evaluate the given saved query, and extract the list of Finding objects from the Query response:

endorctl api get --resource SavedQuery --uuid <insert-uuid> \
  | jq '.spec.query.spec.query_response.list.objects[]'

3 - Using Audit Log API

Learn how to use the audit log API in Endor Labs

Audit logs help to monitor user actions and system operations, and generate audit trails for compliance requirements.

You can use the list AuditLog endpoint to retrieve audit logs.

You can retrieve audit logs for the following resources:

  • Tenants and namespaces
  • Projects
  • Users and user telemetry
  • Repositories and repository versions
  • Scan results
  • Authorization policies
  • Action policies
  • Remediation policies
  • Notification policies
  • Supported tool chains
  • Application telemetry
  • Endor Labs licenses

Run the following command to fetch the entire audit log.

endorctl api list --resource AuditLog --namespace <namespace name>

Operations with the audit log API

You can pass the meta and spec fields with the endorctl list AuditLog command to refine the output based on your requirements. You can combine multiple filters in the same command and use various operators. See Filters for more information on using filters and operators.

The meta and spec options listed are not exhaustive. You can build your command based on the meta and spec fields in the API specification.

Operators

You can use the following operators with the filters.

Operator Description
== Matches objects where a specified field is equal to a specified value.
!= Matches objects where a specified field is NOT equal to a specified value.
< Matches objects where a specified field is less than a specified value.
<= Matches objects where a specified field is less than or equal to a specified value.
> Matches objects where a specified field is greater than a specified value.
>= Matches objects where a specified field is greater than or equal to a specified value.
contains Matches objects where a specified list contains one or more specified values.
in Matches objects where a specified field is equal to one ore more specified values.
matches Matches objects where a specified field matches a specified regex pattern.
exists Matches objects where a specified field in a json payload exists.

Meta fields

You can use the following meta fields.

Meta Field Description
meta.create_time Timestamp of the message creation.
meta.update_time Timestamp of the message update.
meta.upsert_time Timestamp of the message upsert.
meta.created_by User that created the message.
meta.updated_by User that updated the message.

Spec fields

Spec Field Description
spec.message_kind Message type on which the operations are performed. For example, internal.endor.ai.endor.v1.AuthorizationPolicy is the value of spec.message_kind for authorization policy.
spec.message_UUID The UUID of the message.
spec.operation The type of operation.

The following types are supported:

- OPERATION_CREATE

- OPERATION_UPDATE

- OPERATION_DELETE

- OPERATION_UPSERT

spec.payload The operation payload, which contains the message that is being created or updated.
spec.claims Authentication claims array.
spec.remote_address The source IP address.

Timeout in AuditLog API

Since querying audit logs might take more time in comparison with other API operations, you may face a timeout with the error message, ERROR deadline-exceeded: context deadline exceeded. If you face the error, provide a timeout override along with your API command to complete the API call. You can use the --timeout option and provide the override in seconds: endorctl api <command> --timeout <n>s. For example, endoctl api list --resource AuthenticationLog --timeout 30s. The default timeout is 20 seconds.

Examples of using AuditLog API

The following sections provide various scenarios of using the audit log API.

Filter audit log by time range

Audit logs grow with time. You may want to restrict the time period to retrieve meaningful data to investigate activity during a specific timeframe.

The following example retrieves the audit log of the month of January 2025.

endorctl api list --resource AuditLog \
         --namespace demo \
         --filter="meta.create_time >=\"2025-01-01T00:00:00Z\" \
         and meta.create_time <=\"2025-01-31T23:59:59Z\""

Filter audit log by users and time range

You can retrieve the logs of a specific user in a time period.

The following example retrieves the audit log of a user with the name Doe in their claims token.

endorctl api list --resource AuditLog \
  --namespace demo \
  --filter="meta.create_time >=\"2025-02-01T00:00:00Z\" \
  and meta.create_time <=\"2025-02-19T23:59:59Z\" \
  and spec.claims matches \".*firstname=Doe.*\""

The following example retrieves the audit log of all users with endor.ai as the domain in their claims token.

endorctl api list --resource AuditLog \
  --namespace demo \
  --filter="meta.create_time >=\"2025-02-01T00:00:00Z\" \
  and meta.create_time <=\"2025-02-19T23:59:59Z\" \
  and spec.claims matches \".*domain=endor.ai.*\""

Filter audit log based on operation types

You can retrieve the specific audit logs based on a particular operation.

The following retrieves audit logs that pertain to create operation after August 18, 2024.

endorctl api list --resource AuditLog \
   --namespace demo \
   --filter="spec.operation ==[\"OPERATION_CREATE\"] \
   and meta.create_time >=\"2024-08-18T00:00:00Z\""

Filter audit log based on message type

You can retrieve audit logs based on the message type.

You need to provide internal.endor.ai.endor.v1. followed by the message type with the spec.message_kind filter.

The following example retrieves updates to scan results.

endorctl api list --resource AuditLog \
   --namespace nryn \
   --filter="spec.operation ==[\"OPERATION_CREATE\"] \
   and spec.message_kind ==internal.endor.ai.endor.v1.ScanResult \""

Filter audit log based on policy updates

You can retrieve audit logs for the updates on policies.

The following example retrieves updates to action, notification, and remediation policies made after August 18, 2024.

endorctl api list --resource AuditLog \
   --namespace nryn \
   --filter="spec.operation ==[\"OPERATION_CREATE\"] \
   and spec.message_kind ==internal.endor.ai.endor.v1.Policy \
   and meta.create_time >=\"2024-08-18T00:00:00Z\""

The following example retrieves changes to authorization policies made after August 18, 2024.

endorctl api list --resource AuditLog \
   --namespace demo \
   --filter="spec.operation ==[\"OPERATION_UPDATE\"] \
   and spec.message_kind ==internal.endor.ai.endor.v1.AuthorizationPolicy \
   and meta.create_time >=\"2024-08-18T00:00:00Z\""

Filter audit log based on IP range

You can retrieve audit logs based on an IP range to investigate activities originating from a particular geography or a particular service that uses your Endor Labs instance.

The following example retrieves audit log for activities done from the IP range, 10.244.0.0 to 10.244.255.255.

endorctl api list --resource AuditLog \
   --namespace demo \
   --filter="spec.remote_address >=\"10.244.0.0\" \
   and spec.remote_address <=\"10.244.255.255\""

Retrieve the history of an object based on message UUID

You can retrieve the history of an object based on the message UUID.

endorctl api list --resource AuditLog \
   --namespace demo \ --filter="spec.message_uuid==<message_uuid>\"

The following example retrieves the history of an action policy with the UUID, 66axxxxxxxxxx4c15dc1.

endorctl api list --resource AuditLog \
   --namespace demo \
   --filter="spec.message_uuid==\"66axxxxxxxxxx4c15dc1\""