Skip to content

Commit dd0b50d

Browse files
committed
list network interface
1 parent c4e2c79 commit dd0b50d

File tree

18 files changed

+223
-58
lines changed

18 files changed

+223
-58
lines changed

api/api.go

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,36 @@ import (
99
"github.com/sirupsen/logrus"
1010

1111
"github.com/replicatedhq/embedded-cluster/api/controllers/auth"
12+
"github.com/replicatedhq/embedded-cluster/api/controllers/console"
1213
"github.com/replicatedhq/embedded-cluster/api/controllers/install"
1314
"github.com/replicatedhq/embedded-cluster/api/types"
1415
)
1516

1617
type API struct {
17-
installController install.Controller
1818
authController auth.Controller
19+
consoleController console.Controller
20+
installController install.Controller
1921
configChan chan<- *types.InstallationConfig
2022
logger logrus.FieldLogger
2123
}
2224

2325
type APIOption func(*API)
2426

25-
func WithInstallController(installController install.Controller) APIOption {
27+
func WithAuthController(authController auth.Controller) APIOption {
2628
return func(a *API) {
27-
a.installController = installController
29+
a.authController = authController
2830
}
2931
}
3032

31-
func WithAuthController(authController auth.Controller) APIOption {
33+
func WithConsoleController(consoleController console.Controller) APIOption {
3234
return func(a *API) {
33-
a.authController = authController
35+
a.consoleController = consoleController
36+
}
37+
}
38+
39+
func WithInstallController(installController install.Controller) APIOption {
40+
return func(a *API) {
41+
a.installController = installController
3442
}
3543
}
3644

@@ -52,14 +60,6 @@ func New(password string, opts ...APIOption) (*API, error) {
5260
opt(api)
5361
}
5462

55-
if api.installController == nil {
56-
installController, err := install.NewInstallController()
57-
if err != nil {
58-
return nil, fmt.Errorf("new install controller: %w", err)
59-
}
60-
api.installController = installController
61-
}
62-
6363
if api.authController == nil {
6464
authController, err := auth.NewAuthController(password)
6565
if err != nil {
@@ -68,6 +68,22 @@ func New(password string, opts ...APIOption) (*API, error) {
6868
api.authController = authController
6969
}
7070

71+
if api.consoleController == nil {
72+
consoleController, err := console.NewConsoleController()
73+
if err != nil {
74+
return nil, fmt.Errorf("new console controller: %w", err)
75+
}
76+
api.consoleController = consoleController
77+
}
78+
79+
if api.installController == nil {
80+
installController, err := install.NewInstallController()
81+
if err != nil {
82+
return nil, fmt.Errorf("new install controller: %w", err)
83+
}
84+
api.installController = installController
85+
}
86+
7187
if api.logger == nil {
7288
api.logger = NewDiscardLogger()
7389
}
@@ -88,6 +104,9 @@ func (a *API) RegisterRoutes(router *mux.Router) {
88104
installRouter.HandleFunc("/config", a.setInstallConfig).Methods("POST")
89105
installRouter.HandleFunc("/status", a.setInstallStatus).Methods("POST")
90106
installRouter.HandleFunc("/status", a.getInstallStatus).Methods("GET")
107+
108+
consoleRouter := authenticatedRouter.PathPrefix("/console").Subrouter()
109+
consoleRouter.HandleFunc("/available-network-interfaces", a.getListAvailableNetworkInterfaces).Methods("GET")
91110
}
92111

93112
func handleError(w http.ResponseWriter, err error) {

api/auth.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"errors"
66
"net/http"
7+
"strings"
78

89
"github.com/replicatedhq/embedded-cluster/api/controllers/auth"
910
"github.com/replicatedhq/embedded-cluster/api/types"
@@ -14,19 +15,32 @@ type AuthRequest struct {
1415
}
1516

1617
type AuthResponse struct {
17-
SessionToken string `json:"sessionToken"`
18+
Token string `json:"token"`
1819
}
1920

2021
func (a *API) authMiddleware(next http.Handler) http.Handler {
2122
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
22-
sessionToken := r.Header.Get("Authorization")
23-
if sessionToken == "" {
24-
types.NewUnauthorizedError(errors.New("authorization header is required")).JSON(w)
23+
token := r.Header.Get("Authorization")
24+
if token == "" {
25+
err := errors.New("authorization header is required")
26+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
27+
Error("failed to authenticate")
28+
types.NewUnauthorizedError(err).JSON(w)
29+
return
30+
} else if !strings.HasPrefix(token, "Bearer ") {
31+
err := errors.New("authorization header must start with Bearer ")
32+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
33+
Error("failed to authenticate")
34+
types.NewUnauthorizedError(err).JSON(w)
2535
return
2636
}
2737

28-
err := a.authController.ValidateToken(r.Context(), sessionToken)
38+
token = token[len("Bearer "):]
39+
40+
err := a.authController.ValidateToken(r.Context(), token)
2941
if err != nil {
42+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
43+
Error("failed to validate token")
3044
types.NewUnauthorizedError(err).JSON(w)
3145
return
3246
}
@@ -39,21 +53,25 @@ func (a *API) postAuthLogin(w http.ResponseWriter, r *http.Request) {
3953
var request AuthRequest
4054
err := json.NewDecoder(r.Body).Decode(&request)
4155
if err != nil {
56+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
57+
Error("failed to decode auth request")
4258
types.NewBadRequestError(err).JSON(w)
4359
return
4460
}
4561

46-
sessionToken, err := a.authController.Authenticate(r.Context(), request.Password)
62+
token, err := a.authController.Authenticate(r.Context(), request.Password)
4763
if errors.Is(err, auth.ErrInvalidPassword) {
4864
types.NewUnauthorizedError(err).JSON(w)
4965
return
5066
} else if err != nil {
67+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
68+
Error("failed to authenticate")
5169
types.NewInternalServerError(err).JSON(w)
5270
return
5371
}
5472

5573
response := AuthResponse{
56-
SessionToken: sessionToken,
74+
Token: token,
5775
}
5876

5977
json.NewEncoder(w).Encode(response)

api/console.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
)
7+
8+
type getListAvailableNetworkInterfacesResponse struct {
9+
NetworkInterfaces []string `json:"networkInterfaces"`
10+
}
11+
12+
func (a *API) getListAvailableNetworkInterfaces(w http.ResponseWriter, r *http.Request) {
13+
interfaces, err := a.consoleController.ListAvailableNetworkInterfaces()
14+
if err != nil {
15+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
16+
Error("failed to list available network interfaces")
17+
handleError(w, err)
18+
return
19+
}
20+
21+
a.logger.WithFields(logrusFieldsFromRequest(r)).
22+
WithField("interfaces", interfaces).
23+
Info("got available network interfaces")
24+
25+
response := getListAvailableNetworkInterfacesResponse{
26+
NetworkInterfaces: interfaces,
27+
}
28+
29+
json.NewEncoder(w).Encode(response)
30+
}

api/controllers/auth/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func (c *AuthController) Authenticate(ctx context.Context, password string) (str
5151
}
5252

5353
func (c *AuthController) ValidateToken(ctx context.Context, token string) error {
54-
_, err := verifyToken(token)
54+
_, err := validateToken(token)
5555
if err != nil {
5656
return err
5757
}

api/controllers/auth/token.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func getToken(name string) (string, error) {
2121
return tokenString, err
2222
}
2323

24-
func verifyToken(tokenString string) (jwt.Claims, error) {
24+
func validateToken(tokenString string) (jwt.Claims, error) {
2525
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) {
2626
return signingKey, nil
2727
}, jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}))

api/controllers/console/controller.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package console
2+
3+
import (
4+
"github.com/replicatedhq/embedded-cluster/api/pkg/utils"
5+
)
6+
7+
type Controller interface {
8+
ListAvailableNetworkInterfaces() ([]string, error)
9+
}
10+
11+
type ConsoleController struct {
12+
utils.NetUtils
13+
}
14+
15+
type ConsoleControllerOption func(*ConsoleController)
16+
17+
func WithNetUtils(netUtils utils.NetUtils) ConsoleControllerOption {
18+
return func(c *ConsoleController) {
19+
c.NetUtils = netUtils
20+
}
21+
}
22+
23+
func NewConsoleController(opts ...ConsoleControllerOption) (*ConsoleController, error) {
24+
controller := &ConsoleController{}
25+
26+
for _, opt := range opts {
27+
opt(controller)
28+
}
29+
30+
if controller.NetUtils == nil {
31+
controller.NetUtils = utils.NewNetUtils()
32+
}
33+
34+
return controller, nil
35+
}
36+
37+
func (c *ConsoleController) ListAvailableNetworkInterfaces() ([]string, error) {
38+
return c.NetUtils.ListValidNetworkInterfaces()
39+
}

api/install.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ func (a *API) getInstall(w http.ResponseWriter, r *http.Request) {
2323

2424
w.Header().Set("Content-Type", "application/json")
2525
w.WriteHeader(http.StatusOK)
26-
json.NewEncoder(w).Encode(install)
26+
err = json.NewEncoder(w).Encode(install)
27+
if err != nil {
28+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
29+
Error("failed to encode installation")
30+
}
2731
}
2832

2933
func (a *API) setInstallConfig(w http.ResponseWriter, r *http.Request) {
@@ -72,13 +76,19 @@ func (a *API) setInstallStatus(w http.ResponseWriter, r *http.Request) {
7276
func (a *API) getInstallStatus(w http.ResponseWriter, r *http.Request) {
7377
status, err := a.installController.ReadStatus(r.Context())
7478
if err != nil {
79+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
80+
Error("failed to get installation status")
7581
handleError(w, err)
7682
return
7783
}
7884

7985
w.Header().Set("Content-Type", "application/json")
8086
w.WriteHeader(http.StatusOK)
81-
json.NewEncoder(w).Encode(status)
87+
err = json.NewEncoder(w).Encode(status)
88+
if err != nil {
89+
a.logger.WithFields(logrusFieldsFromRequest(r)).WithError(err).
90+
Error("failed to encode installation status")
91+
}
8292
}
8393

8494
func logrusFieldsFromRequest(r *http.Request) logrus.Fields {

api/integration/auth_controller_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func TestAuthLoginAndTokenValidation(t *testing.T) {
2626
// Create an install controller
2727
installController, err := install.NewInstallController(
2828
install.WithInstallationManager(installation.NewInstallationManager(
29-
installation.WithNetUtils(&mockNetUtils{iface: "eth0"}),
29+
installation.WithNetUtils(&mockNetUtils{ifaces: []string{"eth0", "eth1"}}),
3030
)),
3131
)
3232
require.NoError(t, err)
@@ -69,11 +69,11 @@ func TestAuthLoginAndTokenValidation(t *testing.T) {
6969
require.NoError(t, err)
7070

7171
// Validate that we got a session token
72-
assert.NotEmpty(t, loginResponse.SessionToken)
72+
assert.NotEmpty(t, loginResponse.Token)
7373

7474
// Now use this token to access a protected route
7575
getInstallReq := httptest.NewRequest(http.MethodGet, "/install", nil)
76-
getInstallReq.Header.Set("Authorization", loginResponse.SessionToken)
76+
getInstallReq.Header.Set("Authorization", "Bearer "+loginResponse.Token)
7777
getInstallRec := httptest.NewRecorder()
7878

7979
// Serve the request
@@ -119,7 +119,7 @@ func TestAuthLoginAndTokenValidation(t *testing.T) {
119119
// Test access to protected route with invalid token
120120
t.Run("access protected route with invalid token", func(t *testing.T) {
121121
req := httptest.NewRequest(http.MethodGet, "/install", nil)
122-
req.Header.Set("Authorization", "invalid-token")
122+
req.Header.Set("Authorization", "Bearer "+"invalid-token")
123123
rec := httptest.NewRecorder()
124124

125125
// Serve the request

api/integration/console_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package integration

0 commit comments

Comments
 (0)