302 lines
8.2 KiB
Go
302 lines
8.2 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"slices"
|
|
"text/template"
|
|
|
|
"github.com/zricethezav/gitleaks/v8/cmd/generate/config/base"
|
|
"github.com/zricethezav/gitleaks/v8/cmd/generate/config/rules"
|
|
"github.com/zricethezav/gitleaks/v8/config"
|
|
"github.com/zricethezav/gitleaks/v8/logging"
|
|
)
|
|
|
|
const (
|
|
templatePath = "rules/config.tmpl"
|
|
)
|
|
|
|
//go:generate go run $GOFILE ../../../config/gitleaks.toml
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
_, _ = os.Stderr.WriteString("Specify path to the gitleaks.toml config\n")
|
|
os.Exit(2)
|
|
}
|
|
gitleaksConfigPath := os.Args[1]
|
|
|
|
configRules := []*config.Rule{
|
|
rules.OnePasswordSecretKey(),
|
|
rules.OnePasswordServiceAccountToken(),
|
|
rules.AdafruitAPIKey(),
|
|
rules.AdobeClientID(),
|
|
rules.AdobeClientSecret(),
|
|
rules.AgeSecretKey(),
|
|
rules.AirtableApiKey(),
|
|
rules.AirtablePersonalAccessToken(),
|
|
rules.AlgoliaApiKey(),
|
|
rules.AlibabaAccessKey(),
|
|
rules.AlibabaSecretKey(),
|
|
rules.AmazonBedrockAPIKeyLongLived(),
|
|
rules.AmazonBedrockAPIKeyShortLived(),
|
|
rules.AnthropicAdminApiKey(),
|
|
rules.AnthropicApiKey(),
|
|
rules.ArtifactoryApiKey(),
|
|
rules.ArtifactoryReferenceToken(),
|
|
rules.AsanaClientID(),
|
|
rules.AsanaClientSecret(),
|
|
rules.Atlassian(),
|
|
rules.Authress(),
|
|
rules.AWS(),
|
|
rules.AzureActiveDirectoryClientSecret(),
|
|
rules.BitBucketClientID(),
|
|
rules.BitBucketClientSecret(),
|
|
rules.BittrexAccessKey(),
|
|
rules.BittrexSecretKey(),
|
|
rules.Beamer(),
|
|
rules.CodecovAccessToken(),
|
|
rules.CoinbaseAccessToken(),
|
|
rules.ClickHouseCloud(),
|
|
rules.Clojars(),
|
|
rules.CloudflareAPIKey(),
|
|
rules.CloudflareGlobalAPIKey(),
|
|
rules.CloudflareOriginCAKey(),
|
|
rules.CohereAPIToken(),
|
|
rules.ConfluentAccessToken(),
|
|
rules.ConfluentSecretKey(),
|
|
rules.Contentful(),
|
|
rules.CurlHeaderAuth(),
|
|
rules.CurlBasicAuth(),
|
|
rules.Databricks(),
|
|
rules.DatadogtokenAccessToken(),
|
|
rules.DefinedNetworkingAPIToken(),
|
|
rules.DigitalOceanPAT(),
|
|
rules.DigitalOceanOAuthToken(),
|
|
rules.DigitalOceanRefreshToken(),
|
|
rules.DiscordAPIToken(),
|
|
rules.DiscordClientID(),
|
|
rules.DiscordClientSecret(),
|
|
rules.Doppler(),
|
|
rules.DropBoxAPISecret(),
|
|
rules.DropBoxLongLivedAPIToken(),
|
|
rules.DropBoxShortLivedAPIToken(),
|
|
rules.DroneciAccessToken(),
|
|
rules.Duffel(),
|
|
rules.Dynatrace(),
|
|
rules.EasyPost(),
|
|
rules.EasyPostTestAPI(),
|
|
rules.EtsyAccessToken(),
|
|
rules.FacebookSecret(),
|
|
rules.FacebookAccessToken(),
|
|
rules.FacebookPageAccessToken(),
|
|
rules.FastlyAPIToken(),
|
|
rules.FinicityClientSecret(),
|
|
rules.FinicityAPIToken(),
|
|
rules.FlickrAccessToken(),
|
|
rules.FinnhubAccessToken(),
|
|
rules.FlutterwavePublicKey(),
|
|
rules.FlutterwaveSecretKey(),
|
|
rules.FlutterwaveEncKey(),
|
|
rules.FlyIOAccessToken(),
|
|
rules.FrameIO(),
|
|
rules.Freemius(),
|
|
rules.FreshbooksAccessToken(),
|
|
rules.GoCardless(),
|
|
// TODO figure out what makes sense for GCP
|
|
// rules.GCPServiceAccount(),
|
|
rules.GCPAPIKey(),
|
|
rules.GitHubPat(),
|
|
rules.GitHubFineGrainedPat(),
|
|
rules.GitHubOauth(),
|
|
rules.GitHubApp(),
|
|
rules.GitHubRefresh(),
|
|
rules.GitlabCiCdJobToken(),
|
|
rules.GitlabDeployToken(),
|
|
rules.GitlabFeatureFlagClientToken(),
|
|
rules.GitlabFeedToken(),
|
|
rules.GitlabIncomingMailToken(),
|
|
rules.GitlabKubernetesAgentToken(),
|
|
rules.GitlabOauthAppSecret(),
|
|
rules.GitlabPat(),
|
|
rules.GitlabPatRoutable(),
|
|
rules.GitlabPipelineTriggerToken(),
|
|
rules.GitlabRunnerRegistrationToken(),
|
|
rules.GitlabRunnerAuthenticationToken(),
|
|
rules.GitlabRunnerAuthenticationTokenRoutable(),
|
|
rules.GitlabScimToken(),
|
|
rules.GitlabSessionCookie(),
|
|
rules.GitterAccessToken(),
|
|
rules.GrafanaApiKey(),
|
|
rules.GrafanaCloudApiToken(),
|
|
rules.GrafanaServiceAccountToken(),
|
|
rules.HarnessApiKey(),
|
|
rules.HashiCorpTerraform(),
|
|
rules.HashicorpField(),
|
|
rules.Heroku(),
|
|
rules.HerokuV2(),
|
|
rules.HubSpot(),
|
|
rules.HuggingFaceAccessToken(),
|
|
rules.HuggingFaceOrganizationApiToken(),
|
|
rules.Intercom(),
|
|
rules.Intra42ClientSecret(),
|
|
rules.JFrogAPIKey(),
|
|
rules.JFrogIdentityToken(),
|
|
rules.JWT(),
|
|
rules.JWTBase64(),
|
|
rules.KrakenAccessToken(),
|
|
rules.KubernetesSecret(),
|
|
rules.KucoinAccessToken(),
|
|
rules.KucoinSecretKey(),
|
|
rules.LaunchDarklyAccessToken(),
|
|
rules.LinearAPIToken(),
|
|
rules.LinearClientSecret(),
|
|
rules.LinkedinClientID(),
|
|
rules.LinkedinClientSecret(),
|
|
rules.LobAPIToken(),
|
|
rules.LobPubAPIToken(),
|
|
rules.LookerClientID(),
|
|
rules.LookerClientSecret(),
|
|
rules.MailChimp(),
|
|
rules.MailGunPubAPIToken(),
|
|
rules.MailGunPrivateAPIToken(),
|
|
rules.MailGunSigningKey(),
|
|
rules.MapBox(),
|
|
rules.MattermostAccessToken(),
|
|
rules.MaxMindLicenseKey(),
|
|
rules.Meraki(),
|
|
rules.MessageBirdAPIToken(),
|
|
rules.MessageBirdClientID(),
|
|
rules.NetlifyAccessToken(),
|
|
rules.NewRelicUserID(),
|
|
rules.NewRelicUserKey(),
|
|
rules.NewRelicBrowserAPIKey(),
|
|
rules.NewRelicInsertKey(),
|
|
rules.Notion(),
|
|
rules.NPM(),
|
|
rules.NugetConfigPassword(),
|
|
rules.NytimesAccessToken(),
|
|
rules.OctopusDeployApiKey(),
|
|
rules.OktaAccessToken(),
|
|
rules.OpenAI(),
|
|
rules.OpenshiftUserToken(),
|
|
rules.PerplexityAPIKey(),
|
|
rules.PlaidAccessID(),
|
|
rules.PlaidSecretKey(),
|
|
rules.PlaidAccessToken(),
|
|
rules.PlanetScalePassword(),
|
|
rules.PlanetScaleAPIToken(),
|
|
rules.PlanetScaleOAuthToken(),
|
|
rules.PostManAPI(),
|
|
rules.Prefect(),
|
|
rules.PrivateAIToken(),
|
|
rules.PrivateKey(),
|
|
rules.PrivateKeyPKCS12File(),
|
|
rules.PulumiAPIToken(),
|
|
rules.PyPiUploadToken(),
|
|
rules.RapidAPIAccessToken(),
|
|
rules.ReadMe(),
|
|
rules.RubyGemsAPIToken(),
|
|
rules.ScalingoAPIToken(),
|
|
rules.SendbirdAccessID(),
|
|
rules.SendbirdAccessToken(),
|
|
rules.SendGridAPIToken(),
|
|
rules.SendInBlueAPIToken(),
|
|
rules.SentryAccessToken(),
|
|
rules.SentryOrgToken(),
|
|
rules.SentryUserToken(),
|
|
rules.SettlemintApplicationAccessToken(),
|
|
rules.SettlemintPersonalAccessToken(),
|
|
rules.SettlemintServiceAccessToken(),
|
|
rules.ShippoAPIToken(),
|
|
rules.ShopifyAccessToken(),
|
|
rules.ShopifyCustomAccessToken(),
|
|
rules.ShopifyPrivateAppAccessToken(),
|
|
rules.ShopifySharedSecret(),
|
|
rules.SidekiqSecret(),
|
|
rules.SidekiqSensitiveUrl(),
|
|
rules.SlackBotToken(),
|
|
rules.SlackUserToken(),
|
|
rules.SlackAppLevelToken(),
|
|
rules.SlackConfigurationToken(),
|
|
rules.SlackConfigurationRefreshToken(),
|
|
rules.SlackLegacyBotToken(),
|
|
rules.SlackLegacyWorkspaceToken(),
|
|
rules.SlackLegacyToken(),
|
|
rules.SlackWebHookUrl(),
|
|
rules.Snyk(),
|
|
rules.Sonar(),
|
|
rules.SourceGraph(),
|
|
rules.StripeAccessToken(),
|
|
rules.SquareAccessToken(),
|
|
rules.SquareSpaceAccessToken(),
|
|
rules.SumoLogicAccessID(),
|
|
rules.SumoLogicAccessToken(),
|
|
rules.TeamsWebhook(),
|
|
rules.TelegramBotToken(),
|
|
rules.TravisCIAccessToken(),
|
|
rules.Twilio(),
|
|
rules.TwitchAPIToken(),
|
|
rules.TwitterAPIKey(),
|
|
rules.TwitterAPISecret(),
|
|
rules.TwitterAccessToken(),
|
|
rules.TwitterAccessSecret(),
|
|
rules.TwitterBearerToken(),
|
|
rules.Typeform(),
|
|
rules.VaultBatchToken(),
|
|
rules.VaultServiceToken(),
|
|
rules.YandexAPIKey(),
|
|
rules.YandexAWSAccessToken(),
|
|
rules.YandexAccessToken(),
|
|
rules.ZendeskSecretKey(),
|
|
rules.GenericCredential(),
|
|
rules.InfracostAPIToken(),
|
|
}
|
|
|
|
// ensure rules have unique ids
|
|
ruleLookUp := make(map[string]config.Rule, len(configRules))
|
|
for _, rule := range configRules {
|
|
if err := rule.Validate(); err != nil {
|
|
logging.Fatal().Err(err).
|
|
Str("rule-id", rule.RuleID).
|
|
Msg("Failed to validate rule")
|
|
}
|
|
|
|
// check if rule is in ruleLookUp
|
|
if _, ok := ruleLookUp[rule.RuleID]; ok {
|
|
logging.Fatal().
|
|
Str("rule-id", rule.RuleID).
|
|
Msg("rule id is not unique")
|
|
}
|
|
// TODO: eventually change all the signatures to get ride of this
|
|
// nasty dereferencing.
|
|
ruleLookUp[rule.RuleID] = *rule
|
|
|
|
// Slices are de-duplicated with a map, every iteration has a different order.
|
|
// This is an awkward workaround.
|
|
for _, allowlist := range rule.Allowlists {
|
|
slices.Sort(allowlist.Commits)
|
|
slices.Sort(allowlist.StopWords)
|
|
}
|
|
}
|
|
|
|
tmpl, err := template.ParseFiles(templatePath)
|
|
if err != nil {
|
|
logging.Fatal().Err(err).Msg("Failed to parse template")
|
|
}
|
|
|
|
f, err := os.Create(gitleaksConfigPath)
|
|
if err != nil {
|
|
logging.Fatal().Err(err).Msg("Failed to create rules.toml")
|
|
}
|
|
defer f.Close()
|
|
|
|
cfg := base.CreateGlobalConfig()
|
|
cfg.Rules = ruleLookUp
|
|
for _, allowlist := range cfg.Allowlists {
|
|
slices.Sort(allowlist.Commits)
|
|
slices.Sort(allowlist.StopWords)
|
|
}
|
|
if err = tmpl.Execute(f, cfg); err != nil {
|
|
logging.Fatal().Err(err).Msg("could not execute template")
|
|
}
|
|
}
|