mendapi

package
v0.125.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package mendapi is the client for Mend's v1.3 API: the half of a Mend scan that returns findings.

The Unified Agent uploads an inventory and exits; it reports nothing about what is wrong with what it sent. Findings come from here afterwards, which is why a Mend scan is two phases rather than one command.

Kept apart from the scanner because the two have different failure modes and different things to be careful about. This half talks to a third party over the network, and everything it carries, the user key, the tenant, the product a token names. Is either a credential or names the operator's account.

Index

Constants

View Source
const AlertTypeVulnerability = "SECURITY_VULNERABILITY"

AlertTypeVulnerability is the only alert type that is a security finding.

The others are a different kind of statement: NEW_MAJOR_VERSION is dependency freshness, and REJECTED_BY_POLICY_RESOURCE comes from policy configured in the operator's Mend console. Mapping the last one would let a second policy engine reach into Draugr's verdict, when the point of the gate is that it is decided by a descriptor somebody can read.

Variables

This section is empty.

Functions

This section is empty.

Types

type Alert

type Alert struct {
	Type             string        `json:"type"`
	Level            string        `json:"level"`
	Description      string        `json:"description"`
	DirectDependency bool          `json:"directDependency"`
	Date             string        `json:"date"`
	Library          Library       `json:"library"`
	Vulnerability    Vulnerability `json:"vulnerability"`
}

Alert is one thing Mend has to say about a library in a project.

type AwaitOpts

type AwaitOpts struct {
	ProductToken string
	ProjectName  string
	// RequestToken is what the agent reported for this upload, when it reported one.
	RequestToken string
	// ExpectLibraries is how many dependencies the agent said it resolved. Used when there is no
	// request token: the inventory holding at least that many is evidence the upload was applied,
	// and it compares what arrived against what was sent rather than trusting a clock.
	ExpectLibraries int
	// Timeout bounds the whole wait. Minutes rather than seconds: a large component is exactly
	// when Mend is slowest to process, and also when giving up early does most damage.
	Timeout time.Duration
	// Interval is the first gap between polls; it backs off from there.
	Interval time.Duration
	// Sleep is injectable so tests need not wait. Nil uses a real timer.
	Sleep func(context.Context, time.Duration) error
}

AwaitOpts configures the wait for an upload to be processed.

type Client

type Client struct {
	// BaseURL is the tenant, e.g. https://saas.mend.io. The API path is appended.
	BaseURL string
	// UserKey authenticates every request. Never logged, never rendered into a finding.
	UserKey string
	// HTTP is injectable so tests need no network.
	HTTP *http.Client
}

Client talks to one Mend tenant.

func New

func New(baseURL, userKey string) *Client

New returns a Client for a tenant.

func (*Client) Alerts

func (c *Client) Alerts(ctx context.Context, projectToken string) ([]Alert, error)

Alerts returns every alert on a project.

func (*Client) Await

func (c *Client) Await(ctx context.Context, opts AwaitOpts) ([]Alert, error)

Await blocks until the upload identified by RequestToken has been processed, then returns the project's alerts.

The reason this exists: Mend accepts an upload and processes it afterwards, so a query made too early is answered, honestly, with nothing. Nothing is indistinguishable from a clean project, so without this an eager poll turns "has not finished reading your code" into "no vulnerabilities", and does it most reliably on the largest components, because those take longest.

The check is a correlation, not a guess about timing. Where the agent reports an update-request token, the project's vitals carry it once the upload has been applied, which answers "has *my* scan landed" rather than "has *something* happened recently". Where it does not. And the CLI's agent does not print one, the fallback compares the inventory against the number of dependencies the agent said it resolved, which is still evidence about *this* upload rather than about the clock.

**A timeout is an error, never an empty result.** Returning no alerts here would report a pass for a scan nobody has read, which is the failure the whole function exists to prevent.

func (*Client) Inventory added in v0.71.0

func (c *Client) Inventory(ctx context.Context, projectToken string) ([]InventoryLibrary, error)

Inventory returns a project's libraries and the licenses attributed to them.

func (*Client) LibraryCount

func (c *Client) LibraryCount(ctx context.Context, projectToken string) (int, error)

LibraryCount reports how many libraries a project's inventory holds.

The way a caller tells a processed upload from an unprocessed one when the agent gave no request token: the agent says how many dependencies it resolved, so waiting for the inventory to hold that many is self-validating. It compares what arrived against what was sent.

func (*Client) ProjectByName

func (c *Client) ProjectByName(ctx context.Context, productToken, name string) (Project, error)

ProjectByName finds one project in a product by name.

func (*Client) Projects

func (c *Client) Projects(ctx context.Context, productToken string) ([]Project, error)

Projects lists the projects in a product.

func (*Client) Vitals

func (c *Client) Vitals(ctx context.Context, projectToken string) (Vitals, error)

Vitals reports a project's last update.

type Fix

type Fix struct {
	FixResolution string `json:"fixResolution"`
	Message       string `json:"message"`
	URL           string `json:"url"`
}

Fix is Mend's suggested remediation.

type InventoryLibrary added in v0.71.0

type InventoryLibrary struct {
	Name       string             `json:"name"`
	Version    string             `json:"version"`
	Filename   string             `json:"filename"`
	Type       string             `json:"type"`
	GroupID    string             `json:"groupId"`
	ArtifactID string             `json:"artifactId"`
	Licenses   []InventoryLicense `json:"licenses"`
}

InventoryLibrary is one component in a project's inventory, with the licenses Mend attributes to it.

type InventoryLicense added in v0.71.0

type InventoryLicense struct {
	Name     string `json:"name"`
	SPDXName string `json:"spdxName"`
	URL      string `json:"url"`
}

InventoryLicense is one license Mend attributes to a library.

Name is Mend's own vocabulary, "BSD 3", "Apache 2.0". And SPDXName is frequently empty, which is the fact the licenses scanner is built around: a policy written in SPDX cannot match a name that is not one.

type Library

type Library struct {
	Name       string `json:"name"`
	Version    string `json:"version"`
	Filename   string `json:"filename"`
	Type       string `json:"type"`
	GroupID    string `json:"groupId"`
	ArtifactID string `json:"artifactId"`
}

Library identifies the component an alert is about.

Filename is the artifact Mend matched, a wheel or a jar, not a path in the repository. There is no repository path in an alert, which is why a Mend finding is coarser than one from a scanner that read the manifest itself.

type Project

type Project struct {
	ID    int64  `json:"projectId"`
	Name  string `json:"projectName"`
	Token string `json:"projectToken"`
}

Project is one project inside a product.

type Vitals

type Vitals struct {
	Name string `json:"name"`
	// RequestToken is the update-request the agent sent. Correlating it is a direct answer to
	// "has my upload been processed", rather than an inference from a clock.
	RequestToken    string `json:"requestToken"`
	LastUpdatedDate string `json:"lastUpdatedDate"`
	CreationDate    string `json:"creationDate"`
}

Vitals is what the API knows about a project's last update.

The reason this type exists: it is how a caller tells "the scan has not landed yet" from "the scan landed and found nothing". Without it an eager poll reports a clean bill of health for a project Mend has not finished reading.

type Vulnerability

type Vulnerability struct {
	Name        string  `json:"name"`
	Severity    string  `json:"severity"`
	Score       float64 `json:"score"`
	Description string  `json:"description"`
	URL         string  `json:"url"`
	PublishDate string  `json:"publishDate"`
	TopFix      *Fix    `json:"topFix,omitempty"`
}

Vulnerability is the CVE an alert reports.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL