Skip to content

Commit

Permalink
refactored processed almost all go vet and lint remarks
Browse files Browse the repository at this point in the history
  • Loading branch information
mvanholsteijn committed Dec 6, 2021
1 parent 4d047e1 commit c3ee25e
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 347 deletions.
49 changes: 26 additions & 23 deletions clusterinfo/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,33 @@ import (
"time"
)

type ClusterInfo struct {
// ConnectInfo provides basie GKE cluster connect information
type ConnectInfo struct {
Name string
Endpoint string
ClusterCaCertificate string
RootCAs *x509.CertPool
}

// map from endpoint to name and certificate
type ClusterInfoMap map[string]*ClusterInfo
// Map provides a lookup for cluster connection information base on the hostname
type Map map[string]*ConnectInfo

type ClusterInfoCache struct {
// Cache provides access to a cached cluster information map
type Cache struct {
ctx context.Context
projectId string
projectID string
credentials *google.Credentials
refresh time.Duration
clusterInfo *ClusterInfoMap
clusterInfo *Map
mutex sync.Mutex
}

func NewClusterInfoCache(ctx context.Context, projectId string, credentials *google.Credentials, refresh time.Duration) (*ClusterInfoCache, error) {
cache := &ClusterInfoCache{
// NewCache creates a cluster info cache which is refreshed every `refresh`
func NewCache(ctx context.Context, projectID string, credentials *google.Credentials, refresh time.Duration) (*Cache, error) {
cache := &Cache{
ctx: ctx,
credentials: credentials,
projectId: projectId,
projectID: projectID,
refresh: refresh,
}
clusterInfo, err := cache.retrieveClusters()
Expand All @@ -49,34 +52,34 @@ func NewClusterInfoCache(ctx context.Context, projectId string, credentials *goo
return cache, nil
}

func (c *ClusterInfoCache) GetClusterInfoForEndpoint(endpoint string) *ClusterInfo {
// GetConnectInfoForEndpoint returns connect information for the host, or nil if not found
func (c *Cache) GetConnectInfoForEndpoint(endpoint string) *ConnectInfo {
host := strings.Split(endpoint, ":")
if r, ok := (*c.clusterInfo)[host[0]]; ok {
return r
} else {
return nil
}
return nil
}

// thread safe get cluster info
func (c *ClusterInfoCache) getClusterInfo() *ClusterInfoMap {
func (c *Cache) getClusterInfo() *Map {
c.mutex.Lock()
defer c.mutex.Unlock()
return c.clusterInfo
}

// thread safe set cluster info
func (c *ClusterInfoCache) setClusterInfo(m *ClusterInfoMap) {
func (c *Cache) setClusterInfo(m *Map) {
c.mutex.Lock()
defer c.mutex.Unlock()
c.clusterInfo = m
}

// returns a copy of the cluster info map
func (c *ClusterInfoCache) GetClusterInfo() *ClusterInfoMap {
result := make(ClusterInfoMap)
// GetMap returns a copy of the cluster info map
func (c *Cache) GetMap() *Map {
result := make(Map)
for k, v := range *c.getClusterInfo() {
result[k] = &ClusterInfo{
result[k] = &ConnectInfo{
Endpoint: v.Endpoint,
Name: v.Name,
ClusterCaCertificate: v.ClusterCaCertificate,
Expand All @@ -86,7 +89,7 @@ func (c *ClusterInfoCache) GetClusterInfo() *ClusterInfoMap {
return &result
}

func (c *ClusterInfoCache) run() {
func (c *Cache) run() {
for {
select {
case <-c.ctx.Done():
Expand Down Expand Up @@ -117,15 +120,15 @@ func createCertPool(name string, clusterCaCertificate string) *x509.CertPool {
return result
}

func (c *ClusterInfoCache) retrieveClusters() (*ClusterInfoMap, error) {
result := make(ClusterInfoMap)
func (c *Cache) retrieveClusters() (*Map, error) {
result := make(Map)

service, err := container.NewService(c.ctx,
option.WithTokenSource(c.credentials.TokenSource))
if err != nil {
return nil, err
}
parent := fmt.Sprintf("projects/%s/locations/-", c.projectId)
parent := fmt.Sprintf("projects/%s/locations/-", c.projectID)
response, err := service.Projects.Locations.Clusters.List(parent).Do()
if err != nil {
return nil, err
Expand All @@ -135,7 +138,7 @@ func (c *ClusterInfoCache) retrieveClusters() (*ClusterInfoMap, error) {
log.Printf("INFO: skipping cluster %s in status %s", cluster.Name, cluster.Status)
continue
}
result[cluster.Endpoint] = &ClusterInfo{
result[cluster.Endpoint] = &ConnectInfo{
Name: cluster.Name,
Endpoint: cluster.Endpoint,
ClusterCaCertificate: cluster.MasterAuth.ClusterCaCertificate,
Expand Down
4 changes: 2 additions & 2 deletions clusterinfo/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ func TestListClusters(t *testing.T) {
if err != nil {
t.Fatal(err)
}
cache, err := NewClusterInfoCache(ctx, creds.ProjectID, creds, time.Second)
cache, err := NewCache(ctx, creds.ProjectID, creds, time.Second)
if err != nil {
t.Fatal(err)
}

clusters := cache.GetClusterInfo()
clusters := cache.GetMap()
if len(*clusters) == 0 {
t.Fatalf("expected at least 1 cluster, found none")
}
Expand Down
51 changes: 27 additions & 24 deletions cmd/client.go → cmd/gke_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cmd

import (
"fmt"
"github.com/binxio/simple-iap-proxy/client"
"github.com/binxio/simple-iap-proxy/gke_client"
"github.com/spf13/cobra"
"log"
"net/url"
Expand All @@ -22,49 +22,52 @@ func validateClientArguments(cmd *cobra.Command, args []string) error {
return fmt.Errorf("specify either --use-default-credentials or --configuration, not both")
}

if u, err := url.Parse(targetURL); err != nil {
u, err := url.Parse(targetURL)
if err != nil {
return fmt.Errorf("invalid target-url %s, %s", targetURL, err)
} else {
if u.Scheme != "https" {
return fmt.Errorf("target-url must be https")
}
}

if u.Scheme != "https" {
return fmt.Errorf("target-url must be https")
}

return validateRootArguments(cmd, args)
}

func init() {
clientCmd.Flags().StringVarP(&targetURL, "target-url", "t", "", "to forward requests to")
clientCmd.Flags().StringVarP(&audience, "iap-audience", "a", "", "of the IAP application")
clientCmd.Flags().StringVarP(&serviceAccount, "service-account", "s", "", "to impersonate")
clientCmd.Flags().BoolVarP(&useDefaultCredentials, "use-default-credentials", "u", false, "use default credentials instead of gcloud configuration")
clientCmd.Flags().StringVarP(&configurationName, "configuration", "C", "", "name of gcloud configuration to use for credentials")
clientCmd.MarkFlagRequired("iap-audience")
clientCmd.MarkFlagRequired("service-account")
clientCmd.MarkFlagRequired("target-url")
clientCmd.Flags().SortFlags = false
gkeClientCmd.Flags().StringVarP(&targetURL, "target-url", "t", "", "to forward requests to")
gkeClientCmd.Flags().StringVarP(&audience, "iap-audience", "a", "", "of the IAP application")
gkeClientCmd.Flags().StringVarP(&serviceAccount, "service-account", "s", "", "to impersonate")
gkeClientCmd.Flags().BoolVarP(&useDefaultCredentials, "use-default-credentials", "u", false, "use default credentials instead of gcloud configuration")
gkeClientCmd.Flags().StringVarP(&configurationName, "configuration", "C", "", "name of gcloud configuration to use for credentials")
if err := gkeClientCmd.MarkFlagRequired("iap-audience"); err != nil {
log.Fatal(err)
}
gkeClientCmd.MarkFlagRequired("service-account")
gkeClientCmd.MarkFlagRequired("target-url")
gkeClientCmd.Flags().SortFlags = false
}

var clientCmd = &cobra.Command{
Use: "client",
var gkeClientCmd = &cobra.Command{
Use: "gke-client",
Short: "starts a client side proxy, forwarding requests to the GKE cluster via the IAP",
Long: `The client will start a real HTTP/S proxy and forward any requests for
ip address of GKE cluster master endpoints, to the IAP proxy.
`,
Args: validateClientArguments,
Run: func(cmd *cobra.Command, args []string) {
var err error
if keyFile != "" {
certificate, err = loadCertificate(keyFile)
if err != nil {
log.Fatal(err)
}

certificate, err = loadCertificate(keyFile)
if err != nil {
log.Fatal(err)
}
c := client.Proxy{

c := gke_client.Proxy{
Debug: debug,
Port: port,
ServiceAccount: serviceAccount,
ProjectId: projectID,
ProjectID: projectID,
UseDefaultCredentials: useDefaultCredentials,
ConfigurationName: configurationName,
Audience: audience,
Expand Down
11 changes: 5 additions & 6 deletions cmd/server.go → cmd/gke_server.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
package cmd

import (
"github.com/binxio/simple-iap-proxy/server"
"github.com/binxio/simple-iap-proxy/gke_server"
"github.com/spf13/cobra"
)

func init() {
serverCmd.MarkFlagRequired("key-file")
serverCmd.MarkFlagRequired("certificate-file")
gkeServerCmd.Flags().SortFlags = false
}

var serverCmd = &cobra.Command{
Use: "server",
var gkeServerCmd = &cobra.Command{
Use: "gke-server",
Short: "forwards requests from the load balancer to the appropriate GKE cluster",
Long: `reads the Host header of the http requests and if
it matches the ip address of GKE cluster master endpoint, forwards the request to it.
`,
TraverseChildren: true,
Args: validateRootArguments,
Run: func(cmd *cobra.Command, args []string) {
s := server.ReverseProxy{
s := gke_server.ReverseProxy{
Debug: debug,
Port: port,
ProjectID: projectID,
Expand Down
21 changes: 9 additions & 12 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ with a private master IP address via an IAP proxy. It consists of
a proxy which can be run on the client side, and a reverse-proxy which
is run inside the VPC.
`,

Args: validateRootArguments,
}
)

// Execute the main command
func Execute() error {
return rootCmd.Execute()
}
Expand Down Expand Up @@ -70,15 +72,8 @@ func loadCertificate(keyFile string) (*tls.Certificate, error) {
}

func validateRootArguments(_ *cobra.Command, _ []string) error {
// mis-using the positional argument validator here.
if certificateFile != "" && keyFile == "" || keyFile != "" && certificateFile == "" {
return fmt.Errorf("both --certificate-file and --key-file are required.")
}

if keyFile != "" {
if _, err := loadCertificate(keyFile); err != nil {
return err
}
if _, err := loadCertificate(keyFile); err != nil {
return err
}

return nil
Expand All @@ -92,8 +87,10 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&certificateFile, "certificate-file", "c", "", "certificate of the server")
rootCmd.MarkFlagFilename("key-file")
rootCmd.MarkFlagFilename("certificate-file")
rootCmd.MarkFlagRequired("key-file")
rootCmd.MarkFlagRequired("certificate-file")
rootCmd.PersistentFlags().SortFlags = false

rootCmd.AddCommand(clientCmd)
rootCmd.AddCommand(serverCmd)
rootCmd.Flags().SortFlags = false
rootCmd.AddCommand(gkeClientCmd)
rootCmd.AddCommand(gkeServerCmd)
}
Loading

0 comments on commit c3ee25e

Please sign in to comment.