Skip to content

Commit ae793d7

Browse files
authored
Enable GitHub Realtime authentication (#3929)
GitHub Realtime needs to be able to authenticate. This PR adds relevant fields to the relevant protobuf message, and exports/tweaks some stuff from the github source package to permit its (eventual) use by the GitHub Realtime implementation: The Connector interface and its constructors are now exported Connector.Clone now accepts additional clone arguments The github-specific connection construction has been moved into github.go The injected rate limit handler no longer accepts error reporters that it never uses I also added an API endpoint field to the GitHub Realtime proto message, because we need that too and I was here.
1 parent 5cf64de commit ae793d7

File tree

9 files changed

+749
-487
lines changed

9 files changed

+749
-487
lines changed

pkg/pb/sourcespb/sources.pb.go

Lines changed: 543 additions & 439 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/pb/sourcespb/sources.pb.validate.go

Lines changed: 152 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/sources/github/connector.go

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,17 @@
11
package github
22

33
import (
4-
"fmt"
5-
64
gogit "github.com/go-git/go-git/v5"
75
"github.com/google/go-github/v67/github"
8-
"github.com/trufflesecurity/trufflehog/v3/pkg/log"
9-
106
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
11-
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
127
)
138

149
const cloudEndpoint = "https://api.github.com"
1510

16-
type connector interface {
11+
// Connector abstracts over the authenticated ways to interact with GitHub: cloning and API operations.
12+
type Connector interface {
1713
// APIClient returns a configured GitHub client that can be used for GitHub API operations.
1814
APIClient() *github.Client
1915
// Clone clones a repository using the configured authentication information.
20-
Clone(ctx context.Context, repoURL string) (string, *gogit.Repository, error)
21-
}
22-
23-
func newConnector(source *Source) (connector, error) {
24-
apiEndpoint := source.conn.Endpoint
25-
if apiEndpoint == "" || endsWithGithub.MatchString(apiEndpoint) {
26-
apiEndpoint = cloudEndpoint
27-
}
28-
29-
switch cred := source.conn.GetCredential().(type) {
30-
case *sourcespb.GitHub_GithubApp:
31-
log.RedactGlobally(cred.GithubApp.GetPrivateKey())
32-
return newAppConnector(apiEndpoint, cred.GithubApp)
33-
case *sourcespb.GitHub_BasicAuth:
34-
log.RedactGlobally(cred.BasicAuth.GetPassword())
35-
return newBasicAuthConnector(apiEndpoint, cred.BasicAuth)
36-
case *sourcespb.GitHub_Token:
37-
log.RedactGlobally(cred.Token)
38-
return newTokenConnector(apiEndpoint, cred.Token, source.handleRateLimit)
39-
case *sourcespb.GitHub_Unauthenticated:
40-
return newUnauthenticatedConnector(apiEndpoint)
41-
default:
42-
return nil, fmt.Errorf("unknown connection type")
43-
}
16+
Clone(ctx context.Context, repoURL string, args ...string) (string, *gogit.Repository, error)
4417
}

pkg/sources/github/connector_app.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ type appConnector struct {
1919
installationID int64
2020
}
2121

22-
var _ connector = (*appConnector)(nil)
22+
var _ Connector = (*appConnector)(nil)
2323

24-
func newAppConnector(apiEndpoint string, app *credentialspb.GitHubApp) (*appConnector, error) {
24+
func NewAppConnector(apiEndpoint string, app *credentialspb.GitHubApp) (Connector, error) {
2525
installationID, err := strconv.ParseInt(app.InstallationId, 10, 64)
2626
if err != nil {
2727
return nil, fmt.Errorf("could not parse app installation ID %q: %w", app.InstallationId, err)
@@ -78,7 +78,7 @@ func (c *appConnector) APIClient() *github.Client {
7878
return c.apiClient
7979
}
8080

81-
func (c *appConnector) Clone(ctx context.Context, repoURL string) (string, *gogit.Repository, error) {
81+
func (c *appConnector) Clone(ctx context.Context, repoURL string, args ...string) (string, *gogit.Repository, error) {
8282
// TODO: Check rate limit for this call.
8383
token, _, err := c.installationClient.Apps.CreateInstallationToken(
8484
ctx,
@@ -88,7 +88,7 @@ func (c *appConnector) Clone(ctx context.Context, repoURL string) (string, *gogi
8888
return "", nil, fmt.Errorf("could not create installation token: %w", err)
8989
}
9090

91-
return git.CloneRepoUsingToken(ctx, token.GetToken(), repoURL, "x-access-token")
91+
return git.CloneRepoUsingToken(ctx, token.GetToken(), repoURL, "x-access-token", args...)
9292
}
9393

9494
func (c *appConnector) InstallationClient() *github.Client {

pkg/sources/github/connector_basicauth.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ type basicAuthConnector struct {
1717
password string
1818
}
1919

20-
var _ connector = (*basicAuthConnector)(nil)
20+
var _ Connector = (*basicAuthConnector)(nil)
2121

22-
func newBasicAuthConnector(apiEndpoint string, cred *credentialspb.BasicAuth) (*basicAuthConnector, error) {
22+
func NewBasicAuthConnector(apiEndpoint string, cred *credentialspb.BasicAuth) (Connector, error) {
2323
const httpTimeoutSeconds = 60
2424
httpClient := common.RetryableHTTPClientTimeout(int64(httpTimeoutSeconds))
2525
httpClient.Transport = &github.BasicAuthTransport{
@@ -43,6 +43,6 @@ func (c *basicAuthConnector) APIClient() *github.Client {
4343
return c.apiClient
4444
}
4545

46-
func (c *basicAuthConnector) Clone(ctx context.Context, repoURL string) (string, *gogit.Repository, error) {
47-
return git.CloneRepoUsingToken(ctx, c.password, repoURL, c.username)
46+
func (c *basicAuthConnector) Clone(ctx context.Context, repoURL string, args ...string) (string, *gogit.Repository, error) {
47+
return git.CloneRepoUsingToken(ctx, c.password, repoURL, c.username, args...)
4848
}

pkg/sources/github/connector_token.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ type tokenConnector struct {
1717
apiClient *github.Client
1818
token string
1919
isGitHubEnterprise bool
20-
handleRateLimit func(context.Context, error, ...errorReporter) bool
20+
handleRateLimit func(context.Context, error) bool
2121
user string
2222
userMu sync.Mutex
2323
}
2424

25-
var _ connector = (*tokenConnector)(nil)
25+
var _ Connector = (*tokenConnector)(nil)
2626

27-
func newTokenConnector(apiEndpoint string, token string, handleRateLimit func(context.Context, error, ...errorReporter) bool) (*tokenConnector, error) {
27+
func NewTokenConnector(apiEndpoint string, token string, handleRateLimit func(context.Context, error) bool) (Connector, error) {
2828
const httpTimeoutSeconds = 60
2929
httpClient := common.RetryableHTTPClientTimeout(int64(httpTimeoutSeconds))
3030
tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
@@ -50,11 +50,11 @@ func (c *tokenConnector) APIClient() *github.Client {
5050
return c.apiClient
5151
}
5252

53-
func (c *tokenConnector) Clone(ctx context.Context, repoURL string) (string, *gogit.Repository, error) {
53+
func (c *tokenConnector) Clone(ctx context.Context, repoURL string, args ...string) (string, *gogit.Repository, error) {
5454
if err := c.setUserIfUnset(ctx); err != nil {
5555
return "", nil, err
5656
}
57-
return git.CloneRepoUsingToken(ctx, c.token, repoURL, c.user)
57+
return git.CloneRepoUsingToken(ctx, c.token, repoURL, c.user, args...)
5858
}
5959

6060
func (c *tokenConnector) IsGithubEnterprise() bool {

pkg/sources/github/connector_unauthenticated.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ type unauthenticatedConnector struct {
1515
apiClient *github.Client
1616
}
1717

18-
var _ connector = (*unauthenticatedConnector)(nil)
18+
var _ Connector = (*unauthenticatedConnector)(nil)
1919

20-
func newUnauthenticatedConnector(apiEndpoint string) (*unauthenticatedConnector, error) {
20+
func NewUnauthenticatedConnector(apiEndpoint string) (Connector, error) {
2121
const httpTimeoutSeconds = 60
2222
httpClient := common.RetryableHTTPClientTimeout(int64(httpTimeoutSeconds))
2323
apiClient, err := createGitHubClient(httpClient, apiEndpoint)
@@ -33,6 +33,6 @@ func (c *unauthenticatedConnector) APIClient() *github.Client {
3333
return c.apiClient
3434
}
3535

36-
func (c *unauthenticatedConnector) Clone(ctx context.Context, repoURL string) (string, *gogit.Repository, error) {
37-
return git.CloneRepoUsingUnauthenticated(ctx, repoURL)
36+
func (c *unauthenticatedConnector) Clone(ctx context.Context, repoURL string, args ...string) (string, *gogit.Repository, error) {
37+
return git.CloneRepoUsingUnauthenticated(ctx, repoURL, args...)
3838
}

pkg/sources/github/github.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
"github.com/gobwas/glob"
1818
"github.com/google/go-github/v67/github"
19+
"github.com/trufflesecurity/trufflehog/v3/pkg/log"
1920
"golang.org/x/sync/errgroup"
2021
"google.golang.org/protobuf/proto"
2122
"google.golang.org/protobuf/types/known/anypb"
@@ -64,7 +65,7 @@ type Source struct {
6465
jobPool *errgroup.Group
6566
resumeInfoMutex sync.Mutex
6667
resumeInfoSlice []string
67-
connector connector
68+
connector Connector
6869

6970
includePRComments bool
7071
includeIssueComments bool
@@ -1574,3 +1575,28 @@ func (s *Source) ChunkUnit(ctx context.Context, unit sources.SourceUnit, reporte
15741575
}
15751576
return s.scanRepo(ctx, repoURL, reporter)
15761577
}
1578+
1579+
func newConnector(source *Source) (Connector, error) {
1580+
apiEndpoint := source.conn.Endpoint
1581+
if apiEndpoint == "" || endsWithGithub.MatchString(apiEndpoint) {
1582+
apiEndpoint = cloudEndpoint
1583+
}
1584+
1585+
switch cred := source.conn.GetCredential().(type) {
1586+
case *sourcespb.GitHub_GithubApp:
1587+
log.RedactGlobally(cred.GithubApp.GetPrivateKey())
1588+
return NewAppConnector(apiEndpoint, cred.GithubApp)
1589+
case *sourcespb.GitHub_BasicAuth:
1590+
log.RedactGlobally(cred.BasicAuth.GetPassword())
1591+
return NewBasicAuthConnector(apiEndpoint, cred.BasicAuth)
1592+
case *sourcespb.GitHub_Token:
1593+
log.RedactGlobally(cred.Token)
1594+
return NewTokenConnector(apiEndpoint, cred.Token, func(c context.Context, err error) bool {
1595+
return source.handleRateLimit(c, err)
1596+
})
1597+
case *sourcespb.GitHub_Unauthenticated:
1598+
return NewUnauthenticatedConnector(apiEndpoint)
1599+
default:
1600+
return nil, fmt.Errorf("unknown connection type %T", source.conn.GetCredential())
1601+
}
1602+
}

proto/sources.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,13 @@ message GitHubExperimental {
262262
message GitHubRealtime {
263263
uint32 listener_port = 1;
264264
string webhook_secret = 2;
265+
string endpoint = 3 [(validate.rules).string.uri_ref = true];
266+
oneof credential {
267+
credentials.GitHubApp github_app = 4;
268+
string token = 5;
269+
credentials.Unauthenticated unauthenticated = 6;
270+
credentials.BasicAuth basic_auth = 7;
271+
}
265272
}
266273

267274
message GoogleDrive {

0 commit comments

Comments
 (0)