Skip to content

Commit

Permalink
feat(NET-810): add RAC support for admins
Browse files Browse the repository at this point in the history
admins and superadmins can access and connect to any ingress
different users cannot connect to the same ingress with the same remote device
  • Loading branch information
Aceix committed Dec 13, 2023
1 parent 6a6c55c commit 14692bb
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 52 deletions.
42 changes: 20 additions & 22 deletions controllers/ext_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,30 +355,28 @@ func createExtClient(w http.ResponseWriter, r *http.Request) {
return
}
userName = caller.UserName
if !caller.IsAdmin && !caller.IsSuperAdmin {
if _, ok := caller.RemoteGwIDs[nodeid]; !ok {
err = errors.New("permission denied")
slog.Error("failed to create extclient", "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
return
}
// check if user has a config already for remote access client
extclients, err := logic.GetNetworkExtClients(node.Network)
if err != nil {
slog.Error("failed to get extclients", "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
if _, ok := caller.RemoteGwIDs[nodeid]; (!caller.IsAdmin && !caller.IsSuperAdmin) && !ok {
err = errors.New("permission denied")
slog.Error("failed to create extclient", "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "forbidden"))
return
}
// check if user has a config already for remote access client
extclients, err := logic.GetNetworkExtClients(node.Network)
if err != nil {
slog.Error("failed to get extclients", "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
for _, extclient := range extclients {
if extclient.RemoteAccessClientID != "" &&
extclient.RemoteAccessClientID == customExtClient.RemoteAccessClientID && nodeid == extclient.IngressGatewayID {
// extclient on the gw already exists for the remote access client
err = errors.New("remote client config already exists on the gateway. it may have been created by another user with this same remote client machine")
slog.Error("failed to create extclient", "user", userName, "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
for _, extclient := range extclients {
if extclient.RemoteAccessClientID != "" &&
extclient.RemoteAccessClientID == customExtClient.RemoteAccessClientID && nodeid == extclient.IngressGatewayID {
// extclient on the gw already exists for the remote access client
err = errors.New("remote client config already exists on the gateway")
slog.Error("failed to create extclient", "user", userName, "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
return
}
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions models/extclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type ExtClient struct {
Enabled bool `json:"enabled" bson:"enabled"`
OwnerID string `json:"ownerid" bson:"ownerid"`
DeniedACLs map[string]struct{} `json:"deniednodeacls" bson:"acls,omitempty"`
RemoteAccessClientID string `json:"remote_access_client_id"`
RemoteAccessClientID string `json:"remote_access_client_id"` // unique ID (MAC address) of RAC machine
}

// CustomExtClient - struct for CustomExtClient params
Expand All @@ -27,5 +27,5 @@ type CustomExtClient struct {
ExtraAllowedIPs []string `json:"extraallowedips,omitempty"`
Enabled bool `json:"enabled,omitempty"`
DeniedACLs map[string]struct{} `json:"deniednodeacls" bson:"acls,omitempty"`
RemoteAccessClientID string `json:"remote_access_client_id"`
RemoteAccessClientID string `json:"remote_access_client_id"` // unique ID (MAC address) of RAC machine
}
91 changes: 63 additions & 28 deletions pro/controllers/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,16 +166,13 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) {
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("failed to fetch user %s, error: %v", username, err), "badrequest"))
return
}
if user.IsAdmin || user.IsSuperAdmin {
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("admins can visit dashboard to create remote clients"), "badrequest"))
return
}
allextClients, err := logic.GetAllExtClients()
if err != nil {
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}

processedAdminNodeIds := make(map[string]struct{})
for _, extClient := range allextClients {
if extClient.RemoteAccessClientID == req.RemoteAccessClientID && extClient.OwnerID == username {
node, err := logic.GetNodeByID(extClient.IngressGatewayID)
Expand All @@ -193,7 +190,7 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) {
continue
}

if _, ok := user.RemoteGwIDs[node.ID.String()]; ok {
if _, ok := user.RemoteGwIDs[node.ID.String()]; (!user.IsAdmin && !user.IsSuperAdmin) && ok {
gws := userGws[node.Network]

gws = append(gws, models.UserRemoteGws{
Expand All @@ -206,39 +203,77 @@ func getUserRemoteAccessGws(w http.ResponseWriter, r *http.Request) {
})
userGws[node.Network] = gws
delete(user.RemoteGwIDs, node.ID.String())

} else {
gws := userGws[node.Network]
gws = append(gws, models.UserRemoteGws{
GwID: node.ID.String(),
GWName: host.Name,
Network: node.Network,
GwClient: extClient,
Connected: true,
IsInternetGateway: node.IsInternetGateway,
})
userGws[node.Network] = gws
processedAdminNodeIds[node.ID.String()] = struct{}{}
}
}

}

// add remaining gw nodes to resp
for gwID := range user.RemoteGwIDs {
node, err := logic.GetNodeByID(gwID)
if err != nil {
continue
}
if !node.IsIngressGateway {
continue
}
if node.PendingDelete {
continue
if !user.IsAdmin && !user.IsSuperAdmin {
for gwID := range user.RemoteGwIDs {
node, err := logic.GetNodeByID(gwID)
if err != nil {
continue
}
if !node.IsIngressGateway {
continue
}
if node.PendingDelete {
continue
}
host, err := logic.GetHost(node.HostID.String())
if err != nil {
continue
}
gws := userGws[node.Network]

gws = append(gws, models.UserRemoteGws{
GwID: node.ID.String(),
GWName: host.Name,
Network: node.Network,
IsInternetGateway: node.IsInternetGateway,
})
userGws[node.Network] = gws
}
host, err := logic.GetHost(node.HostID.String())
} else {
allNodes, err := logic.GetAllNodes()
if err != nil {
continue
slog.Error("failed to fetch all nodes", "error", err)
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
return
}
gws := userGws[node.Network]
for _, node := range allNodes {
_, ok := processedAdminNodeIds[node.ID.String()]
if node.IsIngressGateway && !node.PendingDelete && !ok {
host, err := logic.GetHost(node.HostID.String())
if err != nil {
slog.Error("failed to fetch host", "error", err)
continue
}
gws := userGws[node.Network]

gws = append(gws, models.UserRemoteGws{
GwID: node.ID.String(),
GWName: host.Name,
Network: node.Network,
IsInternetGateway: node.IsInternetGateway,
})
userGws[node.Network] = gws
gws = append(gws, models.UserRemoteGws{
GwID: node.ID.String(),
GWName: host.Name,
Network: node.Network,
IsInternetGateway: node.IsInternetGateway,
})
userGws[node.Network] = gws
}
}
}

slog.Debug("returned user gws", "user", username, "gws", userGws)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(userGws)
}
Expand Down

0 comments on commit 14692bb

Please sign in to comment.