mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SecretScan: Remove placeholder image and polish errors (#61785)
* remove placeholder image * improve http client options * add http clients options for webhook notifier * ensure http is only used in dev mode * cleanup errors
This commit is contained in:
parent
ed076adde5
commit
e2ec219f6a
@ -78,7 +78,13 @@ func ProvideServiceAccountsService(
|
||||
s.secretScanInterval = cfg.SectionWithEnvOverrides("secretscan").
|
||||
Key("interval").MustDuration(defaultSecretScanInterval)
|
||||
if s.secretScanEnabled {
|
||||
s.secretScanService = secretscan.NewService(s.store, cfg)
|
||||
var errSecret error
|
||||
s.secretScanService, errSecret = secretscan.NewService(s.store, cfg)
|
||||
if errSecret != nil {
|
||||
s.secretScanEnabled = false
|
||||
s.log.Warn("failed to initialize secret scan service. secret scan is disabled",
|
||||
"error", errSecret.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return s, nil
|
||||
|
@ -3,9 +3,12 @@ package secretscan
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -34,19 +37,37 @@ type Token struct {
|
||||
ReportedAt string `json:"reported_at"` //nolint
|
||||
}
|
||||
|
||||
var ErrInvalidStatusCode = errors.New("invalid status code")
|
||||
var (
|
||||
ErrInvalidStatusCode = errors.New("invalid status code")
|
||||
errSecretScanURL = errors.New("secretscan url must be https")
|
||||
)
|
||||
|
||||
func newClient(url, version string, dev bool) (*client, error) {
|
||||
if !strings.HasPrefix(url, "https://") && !dev {
|
||||
return nil, errSecretScanURL
|
||||
}
|
||||
|
||||
func newClient(url, version string) *client {
|
||||
return &client{
|
||||
version: version,
|
||||
baseURL: url,
|
||||
httpClient: &http.Client{
|
||||
Timeout: timeout,
|
||||
Transport: nil,
|
||||
CheckRedirect: nil,
|
||||
Jar: nil,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
Renegotiation: tls.RenegotiateFreelyAsClient,
|
||||
},
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: timeout,
|
||||
KeepAlive: 15 * time.Second,
|
||||
}).DialContext,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
},
|
||||
Timeout: time.Second * 30,
|
||||
},
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// checkTokens checks if any leaked tokens exist.
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
const defaultURL = "https://secretscan.grafana.com"
|
||||
const defaultURL = "https://secret-scanning.grafana.net"
|
||||
|
||||
type Checker interface {
|
||||
CheckTokens(ctx context.Context) error
|
||||
@ -40,20 +40,34 @@ type Service struct {
|
||||
revoke bool // whether to revoke leaked tokens
|
||||
}
|
||||
|
||||
func NewService(store SATokenRetriever, cfg *setting.Cfg) *Service {
|
||||
func NewService(store SATokenRetriever, cfg *setting.Cfg) (*Service, error) {
|
||||
secretscanBaseURL := cfg.SectionWithEnvOverrides("secretscan").Key("base_url").MustString(defaultURL)
|
||||
// URL to send outgoing webhook when a token is leaked.
|
||||
oncallURL := cfg.SectionWithEnvOverrides("secretscan").Key("oncall_url").MustString("")
|
||||
revoke := cfg.SectionWithEnvOverrides("secretscan").Key("revoke").MustBool(true)
|
||||
|
||||
client, err := newClient(secretscanBaseURL, cfg.BuildVersion, cfg.Env == setting.Dev)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create secretscan client: %w", err)
|
||||
}
|
||||
|
||||
var webHookClient WebHookClient
|
||||
if oncallURL != "" {
|
||||
var errWebhook error
|
||||
webHookClient, errWebhook = newWebHookClient(oncallURL, cfg.BuildVersion, cfg.Env == setting.Dev)
|
||||
if errWebhook != nil {
|
||||
return nil, fmt.Errorf("failed to create secretscan webhook client: %w", errWebhook)
|
||||
}
|
||||
}
|
||||
|
||||
return &Service{
|
||||
store: store,
|
||||
client: newClient(secretscanBaseURL, cfg.BuildVersion),
|
||||
webHookClient: newWebHookClient(oncallURL, cfg.BuildVersion),
|
||||
client: client,
|
||||
webHookClient: webHookClient,
|
||||
logger: log.New("secretscan"),
|
||||
webHookNotify: oncallURL != "",
|
||||
revoke: revoke,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) RetrieveActiveTokens(ctx context.Context) ([]apikey.APIKey, error) {
|
||||
|
@ -3,14 +3,20 @@ package secretscan
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var errWebHookURL = errors.New("webhook url must be https")
|
||||
|
||||
// webHookClient is a client for sending leak notifications.
|
||||
type webHookClient struct {
|
||||
httpClient *http.Client
|
||||
@ -20,17 +26,32 @@ type webHookClient struct {
|
||||
|
||||
var ErrInvalidWebHookStatusCode = errors.New("invalid webhook status code")
|
||||
|
||||
func newWebHookClient(url, version string) *webHookClient {
|
||||
func newWebHookClient(url, version string, dev bool) (*webHookClient, error) {
|
||||
if !strings.HasPrefix(url, "https://") && !dev {
|
||||
return nil, errWebHookURL
|
||||
}
|
||||
|
||||
return &webHookClient{
|
||||
version: version,
|
||||
url: url,
|
||||
httpClient: &http.Client{
|
||||
Transport: nil,
|
||||
CheckRedirect: nil,
|
||||
Jar: nil,
|
||||
Timeout: timeout,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
Renegotiation: tls.RenegotiateFreelyAsClient,
|
||||
},
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: timeout,
|
||||
KeepAlive: 15 * time.Second,
|
||||
}).DialContext,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
},
|
||||
Timeout: time.Second * 30,
|
||||
},
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (wClient *webHookClient) Notify(ctx context.Context,
|
||||
@ -45,7 +66,6 @@ func (wClient *webHookClient) Notify(ctx context.Context,
|
||||
values := map[string]interface{}{
|
||||
"alert_uid": uuid.NewString(),
|
||||
"title": "SecretScan Alert: Grafana Token leaked",
|
||||
"image_url": "https://images.pexels.com/photos/5119737/pexels-photo-5119737.jpeg?auto=compress&cs=tinysrgb&w=300", //nolint
|
||||
"state": "alerting",
|
||||
"link_to_upstream_details": token.URL,
|
||||
"message": "Token of type " +
|
||||
|
Loading…
Reference in New Issue
Block a user