Skip to content

Commit

Permalink
enhance: private key path support
Browse files Browse the repository at this point in the history
  • Loading branch information
plyr4 committed Dec 19, 2024
1 parent 5a39382 commit 6893af8
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 22 deletions.
26 changes: 26 additions & 0 deletions api/scm/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,31 @@ func SyncRepo(c *gin.Context) {
}
}

// map this repo to an installation, if necessary
installID := r.GetInstallID()

r, err = scm.FromContext(c).SyncRepoWithInstallation(ctx, r)
if err != nil {
retErr := fmt.Errorf("unable to sync repo %s with installation: %w", r.GetFullName(), err)

util.HandleError(c, http.StatusInternalServerError, retErr)

return
}

// install_id was synced
if r.GetInstallID() != installID {
_, err := database.FromContext(c).UpdateRepo(ctx, r)
if err != nil {
retErr := fmt.Errorf("unable to update repo %s during repair: %w", r.GetFullName(), err)

util.HandleError(c, http.StatusInternalServerError, retErr)

return
}

l.Tracef("repo %s install_id synced to %d", r.GetFullName(), r.GetInstallID())
}

c.Status(http.StatusNoContent)
}
1 change: 1 addition & 0 deletions cmd/vela-server/scm.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func setupSCM(c *cli.Context, tc *tracing.Client) (scm.Service, error) {
ClientSecret: c.String("scm.secret"),
AppID: c.Int64("scm.app.id"),
AppPrivateKey: c.String("scm.app.private-key"),
AppPrivateKeyPath: c.String("scm.app.private-key.path"),
AppPermissions: c.StringSlice("scm.app.permissions"),
ServerAddress: c.String("server-addr"),
ServerWebhookAddress: c.String("scm.webhook.addr"),
Expand Down
6 changes: 6 additions & 0 deletions scm/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ var Flags = []cli.Flag{
Name: "scm.app.private-key",
Usage: "set value of base64 encoded SCM App integration (GitHub App) private key",
},
&cli.StringFlag{
EnvVars: []string{"VELA_SCM_APP_PRIVATE_KEY_PATH", "SCM_APP_PRIVATE_KEY_PATH"},
FilePath: "/vela/scm/app_private_key_path",
Name: "scm.app.private-key.path",
Usage: "set filepath to the SCM App integration (GitHub App) private key",
},
&cli.StringSliceFlag{
EnvVars: []string{"VELA_SCM_APP_PERMISSIONS", "SCM_APP_PERMISSIONS", "VELA_SOURCE_APP_PERMISSIONS", "SOURCE_APP_PERMISSIONS"},
FilePath: "/vela/scm/app/permissions",
Expand Down
22 changes: 2 additions & 20 deletions scm/github/app_transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -47,23 +44,8 @@ type AppsTransport struct {
}

// newGitHubAppTransport creates a new GitHub App transport for authenticating as the GitHub App.
func (c *client) newGitHubAppTransport(appID int64, privateKey, baseURL string) (*AppsTransport, error) {
decodedPEM, err := base64.StdEncoding.DecodeString(privateKey)
if err != nil {
return nil, fmt.Errorf("error decoding base64: %w", err)
}

block, _ := pem.Decode(decodedPEM)
if block == nil {
return nil, fmt.Errorf("failed to parse PEM block containing the key")
}

parsedPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse RSA private key: %w", err)
}

transport := c.newAppsTransportFromPrivateKey(http.DefaultTransport, appID, parsedPrivateKey)
func (c *client) newGitHubAppTransport(appID int64, baseURL string, privateKey *rsa.PrivateKey) (*AppsTransport, error) {

Check failure on line 47 in scm/github/app_transport.go

View workflow job for this annotation

GitHub Actions / golangci

[golangci] scm/github/app_transport.go#L47

(*client).newGitHubAppTransport - result 1 (error) is always nil (unparam)
Raw output
scm/github/app_transport.go:47:114: (*client).newGitHubAppTransport - result 1 (error) is always nil (unparam)
func (c *client) newGitHubAppTransport(appID int64, baseURL string, privateKey *rsa.PrivateKey) (*AppsTransport, error) {
                                                                                                                 ^
transport := c.newAppsTransportFromPrivateKey(http.DefaultTransport, appID, privateKey)
transport.BaseURL = baseURL

// apply tracing to the transport
Expand Down
48 changes: 46 additions & 2 deletions scm/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ package github

import (
"context"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"os"
"strings"

"github.com/google/go-github/v65/github"
Expand Down Expand Up @@ -40,6 +45,8 @@ type config struct {
AppID int64
// specifies the App private key to use for the GitHub client when interacting with App resources
AppPrivateKey string
// specifies the App private key to use for the GitHub client when interacting with App resources
AppPrivateKeyPath string
// specifics the App permissions set
AppPermissions []string
// specifies the Vela server address to use for the GitHub client
Expand Down Expand Up @@ -118,10 +125,47 @@ func New(ctx context.Context, opts ...ClientOpt) (*client, error) {
Scopes: oauthScopes,
}

if c.config.AppID != 0 && len(c.config.AppPrivateKey) > 0 {
var err error

if c.config.AppID != 0 {
c.Logger.Infof("configurating github app integration for app_id %d", c.config.AppID)

transport, err := c.newGitHubAppTransport(c.config.AppID, c.config.AppPrivateKey, c.config.API)
var privateKeyPEM []byte

if len(c.config.AppPrivateKey) == 0 && len(c.config.AppPrivateKeyPath) == 0 {
return nil, errors.New("GitHub App ID provided but no valid private key was provided in either VELA_SCM_APP_PRIVATE_KEY or VELA_SCM_APP_PRIVATE_KEY_PATH")
}

if len(c.config.AppPrivateKey) > 0 {
privateKeyPEM, err = base64.StdEncoding.DecodeString(c.config.AppPrivateKey)
if err != nil {
return nil, fmt.Errorf("error decoding base64: %w", err)
}
} else {
// try reading from path if necessary
c.Logger.Infof("no VELA_SCM_APP_PRIVATE_KEY provided, reading github app private key from path %s", c.config.AppPrivateKeyPath)

privateKeyPEM, err = os.ReadFile(c.config.AppPrivateKeyPath)
if err != nil {
return nil, err
}
}

if len(privateKeyPEM) == 0 {
return nil, errors.New("GitHub App ID provided but no valid private key was provided in either VELA_SCM_APP_PRIVATE_KEY or VELA_SCM_APP_PRIVATE_KEY_PATH")
}

block, _ := pem.Decode(privateKeyPEM)
if block == nil {
return nil, fmt.Errorf("failed to parse GitHub App private key PEM block containing the key")
}

parsedPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, fmt.Errorf("failed to parse GitHub App RSA private key: %w", err)
}

transport, err := c.newGitHubAppTransport(c.config.AppID, c.config.API, parsedPrivateKey)
if err != nil {
return nil, err
}
Expand Down
12 changes: 12 additions & 0 deletions scm/github/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ func WithGithubPrivateKey(key string) ClientOpt {
}
}

// WithGithubPrivateKeyPath sets the private key path for the GitHub App in the scm client.
func WithGithubPrivateKeyPath(path string) ClientOpt {
return func(c *client) error {
c.Logger.Trace("configuring private key path for GitHub App in github scm client")

// set the private key for the GitHub App in the github client
c.config.AppPrivateKeyPath = path

return nil
}
}

// WithGitHubAppPermissions sets the App permissions in the scm client for GitHub.
func WithGitHubAppPermissions(permissions []string) ClientOpt {
return func(c *client) error {
Expand Down
3 changes: 3 additions & 0 deletions scm/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ type Setup struct {
AppID int64
// specifies App integration private key
AppPrivateKey string
// specifies App integration path to private key
AppPrivateKeyPath string
// specifies App integration permissions set
AppPermissions []string
// specifies the Vela server address to use for the scm client
Expand Down Expand Up @@ -69,6 +71,7 @@ func (s *Setup) Github(ctx context.Context) (Service, error) {
github.WithTracing(s.Tracing),
github.WithGithubAppID(s.AppID),
github.WithGithubPrivateKey(s.AppPrivateKey),
github.WithGithubPrivateKeyPath(s.AppPrivateKeyPath),
github.WithGitHubAppPermissions(s.AppPermissions),
)
}
Expand Down

0 comments on commit 6893af8

Please sign in to comment.