summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api')
-rw-r--r--internal/api/api.go32
-rw-r--r--internal/api/endpoints/endpoints.go17
-rw-r--r--internal/api/profiles/profiles.go39
3 files changed, 72 insertions, 16 deletions
diff --git a/internal/api/api.go b/internal/api/api.go
index a9ea0c0..2268357 100644
--- a/internal/api/api.go
+++ b/internal/api/api.go
@@ -1,3 +1,4 @@
+// Package api implements version 3 of the eduVPN api: https://docs.eduvpn.org/server/v3/api.html
package api
import (
@@ -21,12 +22,18 @@ import (
"github.com/eduvpn/eduvpn-common/types/server"
)
+// Callbacks is the API callback interface
+// It is used to trigger authorization and forward token updates
type Callbacks interface {
+ // TriggerAuth is called when authorization should be triggered
TriggerAuth(context.Context, string, bool) (string, error)
+ // AuthDone is called when authorization has just completed
AuthDone(string, server.Type)
+ // TokensUpdates is called when tokens are updated
TokensUpdated(string, server.Type, eduoauth.Token)
}
+// ServerData is the data for a server that is passed to the API struct
type ServerData struct {
// ID is the identifier for the server
ID string
@@ -44,6 +51,7 @@ type ServerData struct {
DisableAuthorize bool
}
+// API is the top-level struct that each method is defined on
type API struct {
cb Callbacks
// oauth is the oauth object
@@ -91,6 +99,7 @@ func NewAPI(ctx context.Context, clientID string, sd ServerData, cb Callbacks, t
return api, nil
}
+// ErrAuthorizeDisabled is returned when authorization is disabled but is needed to complete
var ErrAuthorizeDisabled = errors.New("cannot authorize as re-authorization is disabled")
func (a *API) authorize(ctx context.Context) (err error) {
@@ -168,11 +177,14 @@ func (a *API) authorizedRetry(ctx context.Context, method string, endpoint strin
return h, body, err
}
+// Disconnect disconnects a client from the server by sending a /disconnect API call
+// This cleans up resources such as WireGuard IP allocation
func (a *API) Disconnect(ctx context.Context) error {
_, _, err := a.authorized(ctx, http.MethodPost, "/disconnect", &httpw.OptionalParams{Timeout: 5 * time.Second})
return err
}
+// Info does the /info API call
func (a *API) Info(ctx context.Context) (*profiles.Info, error) {
_, body, err := a.authorizedRetry(ctx, http.MethodGet, "/info", nil)
if err != nil {
@@ -185,16 +197,16 @@ func (a *API) Info(ctx context.Context) (*profiles.Info, error) {
return &p, nil
}
-type Proxy struct {
- Listen string
- Peer string
-}
-
+// ConnectData is the data that is returned when the /connect call completes without error
type ConnectData struct {
+ // Configuration is the VPN configuration
Configuration string
- Protocol protocol.Protocol
- Expires time.Time
- Proxy *wireguard.Proxy
+ // Protocol tells us what protocol it is, OpenVPN or WireGuard (proxied or not)
+ Protocol protocol.Protocol
+ // Expires tells us when this configuration expires
+ Expires time.Time
+ // Proxy is filled when WireGuard is proxied
+ Proxy *wireguard.Proxy
}
// see https://github.com/eduvpn/documentation/blob/v3/API.md#request-1
@@ -345,12 +357,16 @@ func refreshEndpoints(ctx context.Context, sd ServerData) (*endpoints.List, *end
return &ep.API.V3, &epauth.API.V3, err
}
+// OAuthLogger is defined here to update the internal logger
+// for the eduoauth library
type OAuthLogger struct{}
+// Logf logs a message with parameters
func (ol *OAuthLogger) Logf(msg string, params ...interface{}) {
log.Logger.Debugf(msg, params...)
}
+// Log logs a message
func (ol *OAuthLogger) Log(msg string) {
log.Logger.Debugf("%s", msg)
}
diff --git a/internal/api/endpoints/endpoints.go b/internal/api/endpoints/endpoints.go
index 11e244b..c98d2c7 100644
--- a/internal/api/endpoints/endpoints.go
+++ b/internal/api/endpoints/endpoints.go
@@ -1,3 +1,5 @@
+// Package endpoints defines a wrapper around the various
+// endpoints returned by an eduVPN server in well-known
package endpoints
import (
@@ -5,21 +7,30 @@ import (
"net/url"
)
+// List is the list of endpoints as returned by the eduVPN server
type List struct {
- API string `json:"api_endpoint"`
+ // API is the API endpoint which we use for calls such as /info, /connect, ...
+ API string `json:"api_endpoint"`
+ // Authorization is the authorization endpoint for OAuth
Authorization string `json:"authorization_endpoint"`
- Token string `json:"token_endpoint"`
+ // Token is the token endpoint for OAuth
+ Token string `json:"token_endpoint"`
}
+// Versions is the endpoints separated by API version
type Versions struct {
+ // V2 is the legacy V2 API, this is not used
V2 List `json:"http://eduvpn.org/api#2"`
+ // V3 is the newest API, which we use
V3 List `json:"http://eduvpn.org/api#3"`
}
// Endpoints defines the json format for /.well-known/vpn-user-portal".
type Endpoints struct {
+ // API defines the API endpoints, split by version
API Versions `json:"api"`
- V string `json:"v"`
+ // V is the version string for the server
+ V string `json:"v"`
}
// Validate validates the endpoints by parsing them and checking the scheme is HTTP
diff --git a/internal/api/profiles/profiles.go b/internal/api/profiles/profiles.go
index 111a835..d31bbcc 100644
--- a/internal/api/profiles/profiles.go
+++ b/internal/api/profiles/profiles.go
@@ -1,3 +1,5 @@
+// Package profiles defines a wrapper around the various profiles
+// returned by the /info endpoint
package profiles
import (
@@ -5,27 +7,43 @@ import (
"github.com/eduvpn/eduvpn-common/types/server"
)
+// Profile is the information for a profile
type Profile struct {
- ID string `json:"profile_id"`
- DisplayName string `json:"display_name"`
- VPNProtoList []string `json:"vpn_proto_list"`
+ // ID is the identifier of the profile
+ // Used to select a profile
+ ID string `json:"profile_id"`
+ // DisplayName defines the UI friendly name for the profile
+ DisplayName string `json:"display_name"`
+ // VPNProtoList defines the list of VPN protocols
+ // E.g. wireguard, openvpn
+ VPNProtoList []string `json:"vpn_proto_list"`
+ // VPNProtoTransportList defines the list of VPN protocols including their transport values
+ // E.g. wireguard+udp, openvpn+tcp
VPNProtoTransportList []string `json:"vpn_proto_transport_list"`
- DefaultGateway bool `json:"default_gateway"`
- DNSSearchDomains []string `json:"dns_search_domain_list"`
+ // DefaultGateway specifies whether or not this profile is a default gateway profile
+ DefaultGateway bool `json:"default_gateway"`
+ // DNSSearchDomains specifies the list of dns search domains
+ // This is provided for a Linux client issue
+ // See: https://github.com/eduvpn/python-eduvpn-client/issues/550
+ DNSSearchDomains []string `json:"dns_search_domain_list"`
}
+// ListInfo is the struct that has the profile list
type ListInfo struct {
ProfileList []Profile `json:"profile_list"`
}
+// Info is the top-level struct for the info endpoint
type Info struct {
Info ListInfo `json:"info"`
}
+// Len returns the length of the profile list
func (i Info) Len() int {
return len(i.Info.ProfileList)
}
+// Get returns a profile with id `id`, it returns nil if it is not found
func (i Info) Get(id string) *Profile {
for _, p := range i.Info.ProfileList {
if p.ID == id {
@@ -35,6 +53,8 @@ func (i Info) Get(id string) *Profile {
return nil
}
+// MustIndex gets a profile by index
+// This index must be in the bounds
func (i Info) MustIndex(n int) Profile {
return i.Info.ProfileList[n]
}
@@ -48,6 +68,11 @@ func hasProtocol(protos []string, proto protocol.Protocol) bool {
return false
}
+// ShouldFailover returns whether or not this VPN profile should start a failover procedure
+// This is true when the profile supports a TCP connection
+// If we cannot determine whether it supports a TCP connection
+// (because the server doesn't provide the VPN transport list function yet),
+// we will just check if it supports OpenVPN
func (p *Profile) ShouldFailover() bool {
// old servers don't support it, only failover in case OpenVPN is supported
if len(p.VPNProtoTransportList) == 0 {
@@ -65,14 +90,17 @@ func (p *Profile) ShouldFailover() bool {
return false
}
+// HasOpenVPN returns whether or not the profile has OpenVPN support
func (p *Profile) HasOpenVPN() bool {
return hasProtocol(p.VPNProtoList, protocol.OpenVPN)
}
+// HasWireGuard returns whether or not the profile has WireGuard support
func (p *Profile) HasWireGuard() bool {
return hasProtocol(p.VPNProtoList, protocol.WireGuard)
}
+// FilterWireGuard gets a profile list but without WireGuard profiles
func (i Info) FilterWireGuard() *Info {
var ret []Profile
for _, p := range i.Info.ProfileList {
@@ -87,6 +115,7 @@ func (i Info) FilterWireGuard() *Info {
}
}
+// Public gets the server list as a structure that we return to clients
func (i Info) Public() server.Profiles {
m := make(map[string]server.Profile)
for _, p := range i.Info.ProfileList {