Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion management/server/http/handlers/networks/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type handler struct {

func AddEndpoints(networksManager networks.Manager, resourceManager resources.Manager, routerManager routers.Manager, groupsManager groups.Manager, accountManager account.Manager, router *mux.Router) {
addRouterEndpoints(routerManager, router)
addResourceEndpoints(resourceManager, groupsManager, router)
addResourceEndpoints(resourceManager, groupsManager, accountManager, router)

networksHandler := newHandler(networksManager, resourceManager, routerManager, groupsManager, accountManager)
router.HandleFunc("/networks", networksHandler.getAllNetworks).Methods("GET", "OPTIONS")
Expand Down
100 changes: 97 additions & 3 deletions management/server/http/handlers/networks/resources_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,40 @@ import (

"github.com/gorilla/mux"

"github.com/netbirdio/netbird/management/server/account"
nbcontext "github.com/netbirdio/netbird/management/server/context"
"github.com/netbirdio/netbird/management/server/groups"
"github.com/netbirdio/netbird/management/server/networks/resources"
"github.com/netbirdio/netbird/management/server/networks/resources/types"
nbpeer "github.com/netbirdio/netbird/management/server/peer"
nbtypes "github.com/netbirdio/netbird/management/server/types"
"github.com/netbirdio/netbird/shared/management/http/api"
"github.com/netbirdio/netbird/shared/management/http/util"
"github.com/netbirdio/netbird/shared/management/status"
)

type resourceHandler struct {
resourceManager resources.Manager
groupsManager groups.Manager
accountManager account.Manager
}

func addResourceEndpoints(resourcesManager resources.Manager, groupsManager groups.Manager, router *mux.Router) {
resourceHandler := newResourceHandler(resourcesManager, groupsManager)
func addResourceEndpoints(resourcesManager resources.Manager, groupsManager groups.Manager, accountManager account.Manager, router *mux.Router) {
resourceHandler := newResourceHandler(resourcesManager, groupsManager, accountManager)
router.HandleFunc("/networks/resources", resourceHandler.getAllResourcesInAccount).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.getAllResourcesInNetwork).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources", resourceHandler.createResource).Methods("POST", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.getResource).Methods("GET", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.updateResource).Methods("PUT", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}", resourceHandler.deleteResource).Methods("DELETE", "OPTIONS")
router.HandleFunc("/networks/{networkId}/resources/{resourceId}/temporary-access", resourceHandler.CreateTemporaryAccess).Methods("POST", "OPTIONS")
}

func newResourceHandler(resourceManager resources.Manager, groupsManager groups.Manager) *resourceHandler {
func newResourceHandler(resourceManager resources.Manager, groupsManager groups.Manager, accountManager account.Manager) *resourceHandler {
return &resourceHandler{
resourceManager: resourceManager,
groupsManager: groupsManager,
accountManager: accountManager,
}
}

Expand Down Expand Up @@ -218,3 +225,90 @@ func (h *resourceHandler) deleteResource(w http.ResponseWriter, r *http.Request)

util.WriteJSONObject(r.Context(), w, util.EmptyObject{})
}

func (h *resourceHandler) CreateTemporaryAccess(w http.ResponseWriter, r *http.Request) {
userAuth, err := nbcontext.GetUserAuthFromContext(r.Context())
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

vars := mux.Vars(r)
networkID := vars["networkId"]
if len(networkID) == 0 {
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "invalid network ID"), w)
return
}
resourceID := vars["resourceId"]
if len(resourceID) == 0 {
util.WriteError(r.Context(), status.Errorf(status.InvalidArgument, "invalid resource ID"), w)
return
}

var req api.PeerTemporaryAccessRequest
err = json.NewDecoder(r.Body).Decode(&req)
if err != nil {
util.WriteErrorResponse("couldn't parse JSON request", http.StatusBadRequest, w)
return
}

newPeer := &nbpeer.Peer{}
newPeer.FromAPITemporaryAccessRequest(&req)

targetResource, err := h.resourceManager.GetResource(r.Context(), userAuth.AccountId, userAuth.UserId, networkID, resourceID)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

peer, _, _, err := h.accountManager.AddPeer(r.Context(), userAuth.AccountId, "", userAuth.UserId, newPeer, true)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}

for _, rule := range req.Rules {
protocol, portRange, err := nbtypes.ParseRuleString(rule)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
policy := &nbtypes.Policy{
AccountID: userAuth.AccountId,
Description: "Temporary access policy for peer " + peer.Name,
Name: "Temporary access policy for peer " + peer.Name,
Enabled: true,
Rules: []*nbtypes.PolicyRule{{
Name: "Temporary access rule",
Description: "Temporary access rule",
Enabled: true,
Action: nbtypes.PolicyTrafficActionAccept,
SourceResource: nbtypes.Resource{
Type: nbtypes.ResourceTypePeer,
ID: peer.ID,
},
DestinationResource: nbtypes.Resource{
Type: nbtypes.ResourceType(targetResource.Type.String()),
ID: targetResource.ID,
},
Bidirectional: false,
Protocol: protocol,
PortRanges: []nbtypes.RulePortRange{portRange},
}},
}

_, err = h.accountManager.SavePolicy(r.Context(), userAuth.AccountId, userAuth.UserId, policy, true)
if err != nil {
util.WriteError(r.Context(), err, w)
return
}
}

resp := &api.PeerTemporaryAccessResponse{
Id: peer.ID,
Name: peer.Name,
Rules: req.Rules,
}

util.WriteJSONObject(r.Context(), w, resp)
}
42 changes: 42 additions & 0 deletions shared/management/http/api/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4108,6 +4108,48 @@ paths:
"$ref": "#/components/responses/forbidden"
'500':
"$ref": "#/components/responses/internal_error"
/api/networks/{networkId}/resources/{resourceId}/temporary-access:
post:
summary: Create a Temporary Access Peer
description: Creates a temporary access peer that can be used to access this resource and this resource only. The temporary access peer and its access policies will be automatically deleted after it disconnects.
tags: [ Networks ]
security:
- BearerAuth: [ ]
- TokenAuth: [ ]
parameters:
- in: path
name: networkId
required: true
schema:
type: string
description: The unique identifier of a network
- in: path
name: resourceId
required: true
schema:
type: string
description: The unique identifier of a network resource
requestBody:
description: Temporary Access Peer create request
content:
'application/json':
schema:
$ref: '#/components/schemas/PeerTemporaryAccessRequest'
responses:
'200':
description: Temporary Access Peer response
content:
application/json:
schema:
$ref: '#/components/schemas/PeerTemporaryAccessResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'500':
"$ref": "#/components/responses/internal_error"
/api/networks/{networkId}/routers:
get:
summary: List all Network Routers
Expand Down
3 changes: 3 additions & 0 deletions shared/management/http/api/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading