From 8c14bc797894f6a5635d559613dc2d2d2b136a91 Mon Sep 17 00:00:00 2001 From: Marques Johansson Date: Sat, 7 Oct 2023 22:39:45 -0400 Subject: [PATCH] wip: fix oauth2 token handling for lbaas Signed-off-by: Marques Johansson --- internal/cli/root.go | 40 ++++++++++++------- internal/loadbalancers/create.go | 13 ++++-- .../loadbalancers/infrastructure/manager.go | 2 +- .../infrastructure/token_exchanger.go | 7 +++- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/internal/cli/root.go b/internal/cli/root.go index a4477936..bb5bc7b3 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -21,6 +21,7 @@ package cli import ( + "context" "fmt" "log" "net/http" @@ -34,6 +35,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" + "golang.org/x/oauth2" v1 "github.com/equinix/metal-cli/internal/loadbalancers/api/v1" "github.com/equinix/metal-cli/internal/loadbalancers/infrastructure" @@ -118,16 +120,32 @@ func (c *Client) metalApiConnect(httpClient *http.Client) error { return nil } -func (c *Client) lbaasApiConnect(httpClient *http.Client) error { +func (c *Client) lbaasApiConnect(header http.Header) error { + ctx := context.Background() + config := oauth2.Config{ + Endpoint: oauth2.Endpoint{ + TokenURL: "https://iam.metalctrl.io/token", + }, + } + ts := infrastructure.NewTokenExchanger(c.Token(), nil) + token, err := ts.Token() + if err != nil { + return err + } + client := &http.Client{ + Transport: &headerTransport{ + header: header, + }, + } + ctx = context.WithValue(ctx, oauth2.HTTPClient, client) + client = config.Client(ctx, token) + configuration := v1.NewConfiguration() configuration.Debug = checkEnvForDebug() - token := infrastructure.NewTokenExchanger(c.Token(), httpClient) - token.Token() - configuration.AddDefaultHeader("X-Auth-Token", c.Token()) - configuration.HTTPClient = httpClient + configuration.HTTPClient = client configuration.UserAgent = fmt.Sprintf(uaFormat, c.Version, configuration.UserAgent) - client := v1.NewAPIClient(configuration) - c.lbaasApiClient = client + + c.lbaasApiClient = v1.NewAPIClient(configuration) return nil } @@ -234,13 +252,7 @@ func (c *Client) LoadbalancerAPI(cmd *cobra.Command) *v1.APIClient { } if c.lbaasApiClient == nil { - httpClient := &http.Client{ - Transport: &headerTransport{ - header: getAdditionalHeaders(cmd), - }, - } - - err := c.lbaasApiConnect(httpClient) + err := c.lbaasApiConnect(getAdditionalHeaders(cmd)) if err != nil { log.Fatal(err) } diff --git a/internal/loadbalancers/create.go b/internal/loadbalancers/create.go index cd18777d..6c5f579f 100644 --- a/internal/loadbalancers/create.go +++ b/internal/loadbalancers/create.go @@ -58,7 +58,14 @@ func (c *Client) Create() *cobra.Command { } req := c.projectService.CreateLoadBalancer(context.Background(), projectID) - req.LoadBalancerCreate(*lbaas.NewLoadBalancerCreate(name, locationId, portIds, providerId)) + // opts := lbaas.NewLoadBalancerCreate(name, locationId, portIds, providerId) + opts := &lbaas.LoadBalancerCreate{ + Name: name, + LocationId: locationId, + PortIds: portIds, + ProviderId: providerId, + } + req = req.LoadBalancerCreate(*opts) lb, _, err := req.Execute() if err != nil { return fmt.Errorf("Could not create LoadBalancer: %w", err) @@ -76,11 +83,9 @@ func (c *Client) Create() *cobra.Command { createLoadBalancerCmd.Flags().StringVarP(&projectID, "project-id", "p", "", "The project's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PROJECT_ID environment variable.") createLoadBalancerCmd.Flags().StringVarP(&locationId, "location", "l", "", "The location's ID.") createLoadBalancerCmd.Flags().StringVarP(&providerId, "provider", "r", ProviderID, "The provider ID.") - createLoadBalancerCmd.Flags().StringSliceVarP(&portIds, "port", "o", []string{}, "The port's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PORT_ID environment variable.") + createLoadBalancerCmd.Flags().StringSliceVar(&portIds, "port", []string{}, "The port's UUID. This flag is required, unless specified in the config created by metal init or set as METAL_PORT_ID environment variable.") // TODO(displague) Not sure if this is needed - _ = createLoadBalancerCmd.MarkFlagRequired("port") - _ = createLoadBalancerCmd.MarkFlagRequired("provider") _ = createLoadBalancerCmd.MarkFlagRequired("location") _ = createLoadBalancerCmd.MarkFlagRequired("project-id") _ = createLoadBalancerCmd.MarkFlagRequired("name") diff --git a/internal/loadbalancers/infrastructure/manager.go b/internal/loadbalancers/infrastructure/manager.go index 523a3d5b..d3d67859 100644 --- a/internal/loadbalancers/infrastructure/manager.go +++ b/internal/loadbalancers/infrastructure/manager.go @@ -8,7 +8,7 @@ import ( lbaas "github.com/equinix/metal-cli/internal/loadbalancers/api/v1" ) -const ProviderID = "" +const ProviderID = "loadpvd-gOB_-byp5ebFo7A3LHv2B" var LBMetros = map[string]string{ "da": "lctnloc--uxs0GLeAELHKV8GxO_AI", diff --git a/internal/loadbalancers/infrastructure/token_exchanger.go b/internal/loadbalancers/infrastructure/token_exchanger.go index 540d5da2..1c8552aa 100644 --- a/internal/loadbalancers/infrastructure/token_exchanger.go +++ b/internal/loadbalancers/infrastructure/token_exchanger.go @@ -15,14 +15,19 @@ type TokenExchanger struct { client *http.Client } +var _ oauth2.TokenSource = (*TokenExchanger)(nil) + func NewTokenExchanger(metalAPIKey string, client *http.Client) *TokenExchanger { + if client == nil { + client = http.DefaultClient + } return &TokenExchanger{ metalAPIKey: metalAPIKey, client: client, } } -func (m *TokenExchanger) Token() (*oauth2.Token, error) { +func (m TokenExchanger) Token() (*oauth2.Token, error) { tokenExchangeURL := "https://iam.metalctrl.io/api-keys/exchange" tokenExchangeRequest, err := http.NewRequest("POST", tokenExchangeURL, nil) if err != nil {