Skip to content

Commit

Permalink
Add TLS and auth token support (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
aatarasoff authored Nov 22, 2023
1 parent 96bb9b0 commit e466477
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 25 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,18 @@ modules:
To authenticate with repositories that require authentication, `pbuf-cli` uses `.netrc` file. Ensure your `.netrc` file is properly configured in your home directory with credentials.

In case you are using `pbuf-cli` with the PBUF Registry with static token authentication, you can provide the token in your `.netrc` file as following:
```
machine <registry_host>
token <token>
```

For instance:
```
machine pbuf.cloud
token 1234567890
```

---

### Contribution
Expand Down
31 changes: 26 additions & 5 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"encoding/json"
"log"
"os"
"os/user"
"path/filepath"

"github.com/jdx/go-netrc"
v1 "github.com/pbufio/pbuf-cli/gen/pbuf-registry/v1"
"github.com/pbufio/pbuf-cli/internal/model"
"github.com/pbufio/pbuf-cli/internal/modules"
Expand Down Expand Up @@ -35,12 +38,30 @@ func NewRootCmd() *cobra.Command {
log.Fatalf("failed to create modules config: %v", err)
}

var netrcAuth *netrc.Netrc

usr, err := user.Current()
if err == nil {
netrcAuth, err = netrc.Parse(filepath.Join(usr.HomeDir, ".netrc"))
if err != nil {
log.Printf("no .netrc file found. skipping auth")
}
} else {
log.Printf("failed to fetch current user: %v", err)
}

if modulesConfig.HasRegistry() {
registryClient := registry.NewInsecureClient(modulesConfig)
var registryClient v1.RegistryClient
if modulesConfig.Registry.Insecure {
registryClient = registry.NewInsecureClient(modulesConfig, netrcAuth)
} else {
registryClient = registry.NewSecureClient(modulesConfig, netrcAuth)
}

rootCmd.AddCommand(NewModuleCmd(modulesConfig, registryClient))
rootCmd.AddCommand(NewVendorCmd(modulesConfig, registryClient))
rootCmd.AddCommand(NewVendorCmd(modulesConfig, netrcAuth, registryClient))
} else {
rootCmd.AddCommand(NewVendorCmd(modulesConfig, nil))
rootCmd.AddCommand(NewVendorCmd(modulesConfig, netrcAuth, nil))
}

return rootCmd
Expand Down Expand Up @@ -315,14 +336,14 @@ func NewModuleUpdateCmd(config *model.Config, client v1.RegistryClient) *cobra.C
}

// NewVendorCmd creates cobra command for vendor
func NewVendorCmd(modulesConfig *model.Config, client v1.RegistryClient) *cobra.Command {
func NewVendorCmd(modulesConfig *model.Config, netrcAuth *netrc.Netrc, client v1.RegistryClient) *cobra.Command {
// create vendor command
vendorCmd := &cobra.Command{
Use: "vendor",
Short: "Vendor",
Long: "Vendor is a command to vendor modules",
Run: func(cmd *cobra.Command, args []string) {
err := modules.Vendor(modulesConfig, client)
err := modules.Vendor(modulesConfig, netrcAuth, client)
if err != nil {
log.Fatalf("failed to vendor: %v", err)
}
Expand Down
15 changes: 1 addition & 14 deletions internal/modules/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package modules
import (
"log"
"os"
"os/user"
"path/filepath"

"github.com/jdx/go-netrc"
v1 "github.com/pbufio/pbuf-cli/gen/pbuf-registry/v1"
Expand Down Expand Up @@ -45,18 +43,7 @@ func newProtoPatchers() []patcher.Patcher {
}

// Vendor function that iterate over the modules and vendor proto files from git repositories
func Vendor(config *model.Config, client v1.RegistryClient) error {
usr, err := user.Current()
if err != nil {
log.Printf("failed to get current user")
return err
}

netrcAuth, err := netrc.Parse(filepath.Join(usr.HomeDir, ".netrc"))
if err != nil {
log.Printf("no .netrc file found. skipping auth")
}

func Vendor(config *model.Config, netrcAuth *netrc.Netrc, client v1.RegistryClient) error {
patchers := newProtoPatchers()

for _, module := range config.Modules {
Expand Down
102 changes: 98 additions & 4 deletions internal/registry/client.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,112 @@
package registry

import (
"context"
"crypto/tls"
"crypto/x509"
"log"
"net"

"github.com/jdx/go-netrc"
v1 "github.com/pbufio/pbuf-cli/gen/pbuf-registry/v1"
"github.com/pbufio/pbuf-cli/internal/model"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)

// NewInsecureClient generates insecure grpc client
func NewInsecureClient(config *model.Config) v1.RegistryClient {
grpcClient, _ := grpc.Dial(
config.Registry.Addr,
func NewInsecureClient(config *model.Config, netrcAuth *netrc.Netrc) v1.RegistryClient {
addr := canonicalizeAddr(config.Registry.Addr)

opts := []grpc.DialOption{
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
}

perRPCCredentials := credentialsFromNetrc(getRegistryHost(addr), netrcAuth)
if perRPCCredentials != nil {
opts = append(opts, grpc.WithPerRPCCredentials(perRPCCredentials))
}

grpcClient, _ := grpc.Dial(addr, opts...)

return v1.NewRegistryClient(grpcClient)
}

// NewSecureClient generates secure grpc client
// Should use TLS to secure the connection
func NewSecureClient(config *model.Config, netrcAuth *netrc.Netrc) v1.RegistryClient {
certPool, err := x509.SystemCertPool()
if err != nil {
log.Fatalf("failed to load system cert pool: %v", err)
}

addr := canonicalizeAddr(config.Registry.Addr)

opts := []grpc.DialOption{
grpc.WithTransportCredentials(
credentials.NewTLS(&tls.Config{
RootCAs: certPool,
}),
),
}

perRPCCredentials := credentialsFromNetrc(getRegistryHost(addr), netrcAuth)
if perRPCCredentials != nil {
opts = append(opts, grpc.WithPerRPCCredentials(perRPCCredentials))
}

grpcClient, _ := grpc.Dial(addr, opts...)

return v1.NewRegistryClient(grpcClient)
}

// canonicalizeAddr check has the address port or not
// and add the 6777 port by default
func canonicalizeAddr(addr string) string {
if _, _, err := net.SplitHostPort(addr); err != nil {
return net.JoinHostPort(addr, "6777")
}

return addr
}

// getRegistryHost returns the registry host
func getRegistryHost(addr string) string {
host, _, err := net.SplitHostPort(addr)
if err != nil {
return addr
}

return host
}

type netrcCredential struct {
token string
}

func (n netrcCredential) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
return map[string]string{
"authorization": n.token,
}, nil
}

func (n netrcCredential) RequireTransportSecurity() bool {
return false
}

// credentialsFromNetrc returns the credentials from netrc
func credentialsFromNetrc(host string, netrcAuth *netrc.Netrc) credentials.PerRPCCredentials {
if netrcAuth == nil {
return nil
}

machine := netrcAuth.Machine(host)
if machine == nil {
return nil
}

return &netrcCredential{
token: machine.Get("token"),
}
}
3 changes: 1 addition & 2 deletions pbuf.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
version: v1
name: pbufio/pbuf-cli
registry:
addr: pbuf.cloud:8081
insecure: true
addr: pbuf.cloud
modules:
- name: pbufio/pbuf-registry
path: api/pbuf-registry
Expand Down

0 comments on commit e466477

Please sign in to comment.