gitlab

package
v0.76.0 Latest Latest
Warning

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

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

Documentation

Overview

Package gitlab implements the gitlab source plugin: lists projects ("repositories") and members under a single GitLab group and emits the cross-vendor git_repository and directory_user evidence types — suitable for SOC 2 / ISO 27001 branch-protection, code-review, and identity (MFA/admin/lifecycle) policies.

GitLab is one of several substitutable source-code platforms (GitHub, Bitbucket, future Gitea/Azure DevOps); a policy accepts the git_repository evidence type, not a vendor, so this plugin is immediately usable by every policy that already consumes GitHub repositories (the substitutability principle — docs/architecture/04a-evidence-type-registry.md).

Per the KISS-no-DRY axiom (docs/architecture/04-source-plugins.md §The plugin contract), the plugin caches nothing across Collect calls. N policies bound to this plugin → N invocations of Collect.

Test injection: the API interface mirrors the github plugin — the concrete *sdkAPI (backed by gitlab.com/gitlab-org/api/client-go) satisfies it, and unit tests inject an in-memory fake. The real SDK adapter is exercised by an httptest-backed test; live integration tests against gitlab.com are deferred to the testing revamp.

Period-scoped types: alongside the two configuration snapshots the plugin also emits pull_request (one record per merge request MERGED inside the audit window) and deployment (one record per release to a GitLab environment in the window, failed ones included). GitLab merge requests map onto the cross-vendor pull_request type deliberately — the type is vendor-neutral, so one CC8.1 / ISO A.8.32 change-review policy samples GitHub PRs and GitLab MRs through a single contract. The window arrives as period_start / period_end slot params; a caller that passes none (the conformance harness) gets a trailing one-year window ending at the injected clock, never time.Now().

directory_user (WU-2.2): the plugin also lists the group's members and emits one directory_user per member, mapping AccessLevel ≥ Maintainer (or instance-admin) → is_admin, account state → is_active, and the user's two_factor_enabled → mfa_enabled. 2FA and instance-admin status are only readable with a group-owner / instance-admin token (via the Users API); without that privilege the sdkAPI degrades gracefully and mfa_enabled is best-effort false — documented in docs/configuration.md.

Index

Constants

View Source
const EvidenceTypeDeployment = "deployment"

EvidenceTypeDeployment is the cross-vendor deployment shape — one record per release to a running environment during the period, failed ones included.

View Source
const EvidenceTypeDirectoryUser = "directory_user"

EvidenceTypeDirectoryUser is the cross-vendor directory_user shape this plugin emits for the group's members — identical to the shape the github and okta plugins emit (the same identity evidence type).

View Source
const EvidenceTypePullRequest = "pull_request"

EvidenceTypePullRequest is the cross-vendor pull_request shape — one record per change MERGED during the audit period. A GitLab merge request IS that change; the evidence type is vendor-neutral, so the github and gitlab plugins are substitutable for a change-review policy. It answers "did this change actually get reviewed?", which the git_repository configuration snapshot structurally cannot.

View Source
const EvidenceTypeRepository = "git_repository"

EvidenceTypeRepository is the cross-vendor git_repository shape this plugin emits.

View Source
const SourceID = "gitlab"

SourceID is the registered ID for the gitlab plugin instance.

Variables

This section is empty.

Functions

This section is empty.

Types

type API

type API interface {
	// ListRepos returns all projects under the configured group,
	// normalized into the git_repository contract. Implementations must
	// page transparently — callers receive the full list in one slice.
	ListRepos(ctx context.Context) ([]Repo, error)
	// ListMembers returns all members of the configured group, normalized
	// into the directory_user contract. Implementations must page
	// transparently — callers receive the full list in one slice.
	ListMembers(ctx context.Context) ([]Member, error)
	// ListMergedPullRequests returns the group's merge requests merged
	// inside [start, end], normalized into the pull_request contract.
	// Implementations must page transparently and may over-return —
	// the plugin re-applies the window, so it owns the period semantics
	// regardless of which API implementation is wired in.
	ListMergedPullRequests(ctx context.Context, start, end time.Time) ([]PullRequest, error)
	// ListDeployments returns the group's deployments created inside
	// [start, end], failed ones included, normalized into the deployment
	// contract. Implementations must page transparently and may
	// over-return; the plugin re-applies the window.
	ListDeployments(ctx context.Context, start, end time.Time) ([]Deployment, error)
}

API is the subset of the GitLab REST API the plugin uses. Defining it as an interface lets tests inject a fake without making real network calls; the concrete *sdkAPI satisfies it.

type Deployment added in v0.71.0

type Deployment struct {
	Repository string
	// ID is the vendor-native deployment identifier as a string.
	ID  string
	SHA string
	// Environment is the environment name exactly as GitLab reports it.
	Environment string
	// EnvironmentTier is GitLab's environment tier ("production",
	// "staging", …). Empty when the project never set one, in which case
	// the plugin falls back to the environment name for is_production.
	EnvironmentTier string
	Creator         string
	CreatedAt       time.Time
	// Status is the raw GitLab deployment status (created / running /
	// success / failed / canceled / blocked), normalized by the plugin
	// into the deployment type's closed vocabulary.
	Status string
}

Deployment is one release of code to a GitLab environment during the audit period, including failed ones — a failed production deployment is still a change event an auditor may ask about.

type Member added in v0.39.0

type Member struct {
	Username   string
	Name       string
	Email      string
	MFAEnabled bool
	IsAdmin    bool
	IsActive   bool
}

Member is the subset of fields the plugin extracts from a GitLab group member, normalized into the directory_user contract. Every field maps to a property the consuming policies read so none reads an absent field.

MFAEnabled and the instance-admin component of IsAdmin require a group-owner / instance-admin token (the Users API exposes two_factor_enabled / is_admin); the sdkAPI degrades gracefully when the token can't read them, leaving MFAEnabled best-effort false.

type Options

type Options struct {
	API API
	// Now is injected so tests can produce deterministic CollectedAt
	// values. Production callers leave it nil → time.Now().UTC().
	Now func() time.Time
}

Options is the constructor input.

type Plugin

type Plugin struct {
	// contains filtered or unexported fields
}

Plugin is the in-process gitlab source.

func New

func New(opts Options) *Plugin

New constructs a Plugin around an explicit API implementation. Callers using the real GitLab REST API should use NewFromToken.

func NewFromToken

func NewFromToken(_ context.Context, group, token, baseURL string) (*Plugin, error)

NewFromToken constructs a Plugin backed by the real GitLab REST API for the given group, using the supplied personal-access/group token. A blank baseURL defaults to gitlab.com; self-managed instances pass their own URL. Live integration tests are deferred.

func (*Plugin) Collect

func (p *Plugin) Collect(ctx context.Context, req core.SlotRequest) ([]core.EvidenceRecord, error)

Collect dispatches to the per-type collectors for whichever emitted types the slot accepts, returning their records together. A slot that accepts none of the emitted types is rejected. Records are sorted by ID within each type group; the collector splits them by Type for envelope writing.

func (*Plugin) Emits

func (*Plugin) Emits() []string

Emits returns the evidence types this plugin can produce: project metadata as git_repository, group members as directory_user, and the two period-scoped types — merged merge requests as pull_request and environment releases as deployment.

func (*Plugin) ID

func (*Plugin) ID() string

ID returns the registered plugin ID.

func (*Plugin) Init

func (*Plugin) Init(context.Context, map[string]any) error

Init is a no-op; the constructor has already received configuration.

type PullRequest added in v0.71.0

type PullRequest struct {
	// Repository is the project's full path ("group/project"), the same
	// form git_repository uses for name, so the two types join.
	Repository string
	// Number is the MR iid — the per-project number a customer quotes in
	// a waiver, not the instance-wide id.
	Number       int
	Author       string
	MergedBy     string
	TargetBranch string
	// MergeCommitSHA is the commit the MR produced on the target branch;
	// the adapter substitutes the squash commit when the project squashes
	// and GitLab therefore reports no merge commit.
	MergeCommitSHA string
	MergedAt       time.Time
	// Approvers carries the usernames GitLab reports in approved_by,
	// verbatim — the plugin de-duplicates and drops blanks. Empty when
	// the approvals endpoint could not be read (graceful degradation) or
	// when nobody approved.
	Approvers []string
	// ChecksPassed is true when the newest pipeline attached to the MR
	// succeeded. GitLab exposes no per-check aggregate comparable to
	// GitHub's check runs, so the head pipeline is the CI signal.
	ChecksPassed bool
}

PullRequest is one merge request MERGED into a project under the group during the audit period. The adapter supplies the raw vendor facts — GitLab's flat approver list and the newest MR pipeline's outcome; the plugin derives approval_count / independent_approval_count / approved_before_merge from them, so the normalization is unit-testable without a network.

type Repo

type Repo struct {
	Name            string
	DefaultBranch   string
	ProtectionOn    bool
	RequiredReviews int

	RequiresSignedCommits   bool
	RequiresLinearHistory   bool
	AllowsForcePush         bool
	DismissStaleReviews     bool
	RequireCodeOwnerReviews bool

	IsPrivate bool
	Archived  bool

	SecretScanningEnabled   bool
	PushProtectionEnabled   bool
	DependabotAlertsEnabled bool
	CodeScanningEnabled     bool
}

Repo is the subset of fields the plugin extracts from a GitLab project, normalized into the git_repository contract. Every field maps to a property of the git_repository evidence type so policies never read an absent field.

Fields without a read-only GitLab API analog are left at their zero value and documented at the mapping site (sdkAPI.ListRepos):

  • SecretScanningEnabled / CodeScanningEnabled / DependabotAlertsEnabled (GitLab pipeline SAST/Secret/Dependency scanning is configured in .gitlab-ci.yml, not exposed as a project-settings boolean).

Jump to

Keyboard shortcuts

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