Files
go-github/github/secret_scanning.go
Jam Balaya 52908e2c47 refactor!: Pass the secret scanning body types by value and rename them to ...Request (#4548)
BREAKING CHANGE: `SecretScanningAlertUpdateOptions` and `SecretScanningPatternConfigsUpdateOptions` are renamed to `UpdateSecretScanningAlertRequest` and `UpdateSecretScanningPatternConfigsRequest`; `SecretScanningService.UpdateAlert`, `UpdatePatternConfigsForEnterprise` and `UpdatePatternConfigsForOrg` now take them by value; `UpdateSecretScanningAlertRequest.State` is now `*string`.
2026-10-03 10:25:42 -04:00

402 lines
19 KiB
Go

// Copyright 2022 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// SecretScanningService handles communication with the secret scanning related
// methods of the GitHub API.
type SecretScanningService service
// SecretScanningAlert represents a GitHub secret scanning alert.
type SecretScanningAlert struct {
Number *int `json:"number,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
LocationsURL *string `json:"locations_url,omitempty"`
FirstLocationDetected *SecretScanningAlertLocationDetails `json:"first_location_detected,omitempty"`
HasMoreLocations *bool `json:"has_more_locations,omitempty"`
State *string `json:"state,omitempty"`
Resolution *string `json:"resolution,omitempty"`
ResolvedAt *Timestamp `json:"resolved_at,omitempty"`
ResolvedBy *User `json:"resolved_by,omitempty"`
SecretType *string `json:"secret_type,omitempty"`
SecretTypeDisplayName *string `json:"secret_type_display_name,omitempty"`
Secret *string `json:"secret,omitempty"`
Repository *Repository `json:"repository,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
IsBase64Encoded *bool `json:"is_base64_encoded,omitempty"`
MultiRepo *bool `json:"multi_repo,omitempty"`
PubliclyLeaked *bool `json:"publicly_leaked,omitempty"`
PushProtectionBypassed *bool `json:"push_protection_bypassed,omitempty"`
PushProtectionBypassedBy *User `json:"push_protection_bypassed_by,omitempty"`
PushProtectionBypassedAt *Timestamp `json:"push_protection_bypassed_at,omitempty"`
ResolutionComment *string `json:"resolution_comment,omitempty"`
PushProtectionBypassRequestComment *string `json:"push_protection_bypass_request_comment,omitempty"`
PushProtectionBypassRequestHTMLURL *string `json:"push_protection_bypass_request_html_url,omitempty"`
PushProtectionBypassRequestReviewer *User `json:"push_protection_bypass_request_reviewer,omitempty"`
PushProtectionBypassRequestReviewerComment *string `json:"push_protection_bypass_request_reviewer_comment,omitempty"`
Validity *string `json:"validity,omitempty"`
AssignedTo *User `json:"assigned_to,omitempty"`
ClosureRequestComment *string `json:"closure_request_comment,omitempty"`
ClosureRequestReviewer *User `json:"closure_request_reviewer,omitempty"`
ClosureRequestReviewerComment *string `json:"closure_request_reviewer_comment,omitempty"`
Provider *string `json:"provider,omitempty"`
ProviderSlug *string `json:"provider_slug,omitempty"`
Metadata []*SecretScanningAlertMetadata `json:"metadata,omitempty"`
}
// SecretScanningAlertMetadata represents a metadata key/value pair associated with a secret scanning alert.
type SecretScanningAlertMetadata struct {
Key string `json:"key"`
Value string `json:"value"`
}
// SecretScanningAlertLocation represents the location for a secret scanning alert.
type SecretScanningAlertLocation struct {
Type *string `json:"type,omitempty"`
Details *SecretScanningAlertLocationDetails `json:"details,omitempty"`
}
// SecretScanningAlertLocationDetails represents the location details for a secret scanning alert.
type SecretScanningAlertLocationDetails struct {
Path *string `json:"path,omitempty"`
Startline *int `json:"start_line,omitempty"`
EndLine *int `json:"end_line,omitempty"`
StartColumn *int `json:"start_column,omitempty"`
EndColumn *int `json:"end_column,omitempty"`
BlobSHA *string `json:"blob_sha,omitempty"`
BlobURL *string `json:"blob_url,omitempty"`
CommitSHA *string `json:"commit_sha,omitempty"`
CommitURL *string `json:"commit_url,omitempty"`
PullRequestCommentURL *string `json:"pull_request_comment_url,omitempty"`
}
// SecretScanningAlertListOptions specifies optional parameters to the SecretScanningService.ListAlertsForEnterprise method.
type SecretScanningAlertListOptions struct {
// State of the secret scanning alerts to list. Set to open or resolved to only list secret scanning alerts in a specific state.
State string `url:"state,omitempty"`
// A comma-separated list of secret types to return. By default all secret types are returned.
SecretType string `url:"secret_type,omitempty"`
// A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed.
// Valid resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted or used_in_tests.
Resolution string `url:"resolution,omitempty"`
// A comma-separated list of validities that, when present, will return alerts that match the validities in this list.
// Valid options are active, inactive, and unknown.
Validity string `url:"validity,omitempty"`
// A boolean value representing whether or not to filter alerts by the publicly-leaked tag being present. Default: false.
IsPubliclyLeaked bool `url:"is_publicly_leaked,omitempty"`
// A boolean value representing whether or not to filter alerts by the multi-repo tag being present. Default: false.
IsMultiRepo bool `url:"is_multi_repo,omitempty"`
// The direction to sort the results by. Possible values are: asc, desc. Default: desc.
Direction string `url:"direction,omitempty"`
// The property by which to sort the results. Possible values are: created, updated. Default: created.
Sort string `url:"sort,omitempty"`
ListCursorOptions
// List options can vary on the Enterprise type.
// On Enterprise Cloud, Secret Scan alerts support requesting by page number
// along with providing a cursor for an "after" param.
// See: https://docs.github.com/enterprise-cloud@latest/rest/secret-scanning?apiVersion=2022-11-28#list-secret-scanning-alerts-for-an-organization
// Whereas on Enterprise Server, pagination is by index.
// See: https://docs.github.com/enterprise-server@3.6/rest/secret-scanning?apiVersion=2022-11-28#list-secret-scanning-alerts-for-an-organization
ListOptions
}
// UpdateSecretScanningAlertRequest represents a request to update a secret scanning alert.
type UpdateSecretScanningAlertRequest struct {
// State sets the state of the secret scanning alert. Can be either "open" or "resolved".
// You must provide resolution when you set the state to "resolved".
State *string `json:"state,omitempty"`
// Required when the state is "resolved" and represents the reason for resolving the alert.
// Can be one of: "false_positive", "wont_fix", "revoked", or "used_in_tests".
Resolution *string `json:"resolution,omitempty"`
// An optional comment when closing an alert.
ResolutionComment *string `json:"resolution_comment,omitempty"`
// Assignee is the username of the user to assign to the alert.
Assignee *string `json:"assignee,omitempty"`
// Validity sets the validity of the secret scanning alert. Can be either "active" or "inactive".
Validity *string `json:"validity,omitempty"`
}
// PushProtectionBypassRequest represents the parameters for CreatePushProtectionBypass.
type PushProtectionBypassRequest struct {
// The reason for bypassing push protection.
// Can be one of: false_positive, used_in_tests, will_fix_later
Reason string `json:"reason"`
// PlaceholderID is an identifier used for the bypass request.
// GitHub Secret Scanning provides you with a unique PlaceholderID associated with that specific blocked push.
PlaceholderID string `json:"placeholder_id"`
}
// PushProtectionBypass represents the response from CreatePushProtectionBypass.
type PushProtectionBypass struct {
// The reason for bypassing push protection.
Reason string `json:"reason"`
// The time that the bypass will expire in ISO 8601 format.
ExpireAt *Timestamp `json:"expire_at"`
// The token type this bypass is for.
TokenType string `json:"token_type"`
}
// SecretsScan represents the common fields for a secret scanning scan.
type SecretsScan struct {
Type string `json:"type"`
Status string `json:"status"`
CompletedAt *Timestamp `json:"completed_at,omitempty"`
StartedAt *Timestamp `json:"started_at,omitempty"`
}
// CustomPatternBackfillScan represents a scan with an associated custom pattern.
type CustomPatternBackfillScan struct {
SecretsScan
PatternSlug *string `json:"pattern_slug,omitempty"`
PatternScope *string `json:"pattern_scope,omitempty"`
}
// SecretScanningScanHistory is the top-level struct for the secret scanning API response.
type SecretScanningScanHistory struct {
// Information on incremental scan performed by secret scanning on the repository.
IncrementalScans []*SecretsScan `json:"incremental_scans,omitempty"`
// Information on backfill scan performed by secret scanning on the repository.
BackfillScans []*SecretsScan `json:"backfill_scans,omitempty"`
// Information on pattern update scan performed by secret scanning on the repository.
PatternUpdateScans []*SecretsScan `json:"pattern_update_scans,omitempty"`
// Information on custom pattern backfill scan performed by secret scanning on the repository.
CustomPatternBackfillScans []*CustomPatternBackfillScan `json:"custom_pattern_backfill_scans,omitempty"`
}
// ListAlertsForEnterprise lists secret scanning alerts for eligible repositories in an enterprise, from newest to oldest.
//
// To use this endpoint, you must be a member of the enterprise, and you must use an access token with the repo scope or
// security_events scope. Alerts are only returned for organizations in the enterprise for which you are an organization owner or a security manager.
//
// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#list-secret-scanning-alerts-for-an-enterprise
//
//meta:operation GET /enterprises/{enterprise}/secret-scanning/alerts
func (s *SecretScanningService) ListAlertsForEnterprise(ctx context.Context, enterprise string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) {
u := fmt.Sprintf("enterprises/%v/secret-scanning/alerts", enterprise)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, "GET", u, nil)
if err != nil {
return nil, nil, err
}
var alerts []*SecretScanningAlert
resp, err := s.client.Do(req, &alerts)
if err != nil {
return nil, resp, err
}
return alerts, resp, nil
}
// ListAlertsForOrg lists secret scanning alerts for eligible repositories in an organization, from newest to oldest.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#list-secret-scanning-alerts-for-an-organization
//
//meta:operation GET /orgs/{org}/secret-scanning/alerts
func (s *SecretScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) {
u := fmt.Sprintf("orgs/%v/secret-scanning/alerts", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, "GET", u, nil)
if err != nil {
return nil, nil, err
}
var alerts []*SecretScanningAlert
resp, err := s.client.Do(req, &alerts)
if err != nil {
return nil, resp, err
}
return alerts, resp, nil
}
// ListAlertsForRepo lists secret scanning alerts for a private repository, from newest to oldest.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#list-secret-scanning-alerts-for-a-repository
//
//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts
func (s *SecretScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, "GET", u, nil)
if err != nil {
return nil, nil, err
}
var alerts []*SecretScanningAlert
resp, err := s.client.Do(req, &alerts)
if err != nil {
return nil, resp, err
}
return alerts, resp, nil
}
// GetAlert gets a single secret scanning alert detected in a private repository.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#get-a-secret-scanning-alert
//
//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}
func (s *SecretScanningService) GetAlert(ctx context.Context, owner, repo string, number int64) (*SecretScanningAlert, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number)
req, err := s.client.NewRequest(ctx, "GET", u, nil)
if err != nil {
return nil, nil, err
}
var alert *SecretScanningAlert
resp, err := s.client.Do(req, &alert)
if err != nil {
return nil, resp, err
}
return alert, resp, nil
}
// UpdateAlert updates the status of a secret scanning alert in a private repository.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#update-a-secret-scanning-alert
//
//meta:operation PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}
func (s *SecretScanningService) UpdateAlert(ctx context.Context, owner, repo string, number int64, body UpdateSecretScanningAlertRequest) (*SecretScanningAlert, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number)
req, err := s.client.NewRequest(ctx, "PATCH", u, body)
if err != nil {
return nil, nil, err
}
var alert *SecretScanningAlert
resp, err := s.client.Do(req, &alert)
if err != nil {
return nil, resp, err
}
return alert, resp, nil
}
// ListLocationsForAlert lists all locations for a given secret scanning alert for a private repository.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#list-locations-for-a-secret-scanning-alert
//
//meta:operation GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations
func (s *SecretScanningService) ListLocationsForAlert(ctx context.Context, owner, repo string, number int64, opts *ListOptions) ([]*SecretScanningAlertLocation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v/locations", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(ctx, "GET", u, nil)
if err != nil {
return nil, nil, err
}
var locations []*SecretScanningAlertLocation
resp, err := s.client.Do(req, &locations)
if err != nil {
return nil, resp, err
}
return locations, resp, nil
}
// CreatePushProtectionBypass creates a push protection bypass for a given repository.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#create-a-push-protection-bypass
//
//meta:operation POST /repos/{owner}/{repo}/secret-scanning/push-protection-bypasses
func (s *SecretScanningService) CreatePushProtectionBypass(ctx context.Context, owner, repo string, body PushProtectionBypassRequest) (*PushProtectionBypass, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/secret-scanning/push-protection-bypasses", owner, repo)
req, err := s.client.NewRequest(ctx, "POST", u, body)
if err != nil {
return nil, nil, err
}
var pushProtectionBypass *PushProtectionBypass
resp, err := s.client.Do(req, &pushProtectionBypass)
if err != nil {
return nil, resp, err
}
return pushProtectionBypass, resp, nil
}
// GetScanHistory fetches the secret scanning history for a given repository.
//
// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with
// the repo scope or security_events scope and gitHub advanced security or secret scanning must be enabled.
//
// GitHub API docs: https://docs.github.com/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#get-secret-scanning-scan-history-for-a-repository
//
//meta:operation GET /repos/{owner}/{repo}/secret-scanning/scan-history
func (s *SecretScanningService) GetScanHistory(ctx context.Context, owner, repo string) (*SecretScanningScanHistory, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/secret-scanning/scan-history", owner, repo)
req, err := s.client.NewRequest(ctx, "GET", u, nil)
if err != nil {
return nil, nil, err
}
var secretScanningHistory *SecretScanningScanHistory
resp, err := s.client.Do(req, &secretScanningHistory)
if err != nil {
return nil, resp, err
}
return secretScanningHistory, resp, nil
}