diff options
| author | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-05-05 17:47:36 +0200 |
|---|---|---|
| committer | jwijenbergh <jeroenwijenbergh@protonmail.com> | 2022-05-05 17:47:36 +0200 |
| commit | 7bb7885f6eb19547b906513d2664e3730ef5b593 (patch) | |
| tree | ce387ad24da5e3ba3b4d1604d07a5b11d9e68a2e /docs/src/api | |
| parent | 657776055cd07c1f9279e982fbfef88dca1ca71b (diff) | |
Docs: Add API and building improvements
Diffstat (limited to 'docs/src/api')
| -rw-r--r-- | docs/src/api/README.md | 1 | ||||
| -rw-r--r-- | docs/src/api/go/README.md | 9 | ||||
| -rw-r--r-- | docs/src/api/go/example.md | 63 | ||||
| -rw-r--r-- | docs/src/api/go/functions.md | 61 | ||||
| -rw-r--r-- | docs/src/api/overview/README.md | 8 | ||||
| -rw-r--r-- | docs/src/api/overview/connecting.md | 14 | ||||
| -rw-r--r-- | docs/src/api/overview/deregistering.md | 11 | ||||
| -rw-r--r-- | docs/src/api/overview/discovery.md | 63 | ||||
| -rw-r--r-- | docs/src/api/overview/flow.md | 8 | ||||
| -rw-r--r-- | docs/src/api/overview/getconfig.md | 73 | ||||
| -rw-r--r-- | docs/src/api/overview/registering.md | 35 | ||||
| -rw-r--r-- | docs/src/api/python/README.md | 11 | ||||
| -rw-r--r-- | docs/src/api/python/example.md | 48 | ||||
| -rw-r--r-- | docs/src/api/python/functions.md | 69 |
14 files changed, 473 insertions, 1 deletions
diff --git a/docs/src/api/README.md b/docs/src/api/README.md index 5932792..0b7ec55 100644 --- a/docs/src/api/README.md +++ b/docs/src/api/README.md @@ -1 +1,2 @@ # API +This section gives the documentation for the API. We first give an overview of the API in a language-agnostic way. Afterwards, we continue with the language specific documentation. We recommend to read both to get a complete picture, regardless of the language you're using. diff --git a/docs/src/api/go/README.md b/docs/src/api/go/README.md index 452b575..6106f1e 100644 --- a/docs/src/api/go/README.md +++ b/docs/src/api/go/README.md @@ -1 +1,10 @@ # Go +The API that has no additional wrapper code is the Go API. To begin to use the Go library in a Go client you first need to import it: + +```go +import "github.com/jwijenbergh/eduvpn-common" +``` + +This brings the library into scope using the eduvpn-common prefix. + +The functions that we define all operate on a `VPNState` object, thus to call a function it needs to be first created and then the function needs to be called. An example of how to tie all of this together is done at the end. diff --git a/docs/src/api/go/example.md b/docs/src/api/go/example.md new file mode 100644 index 0000000..e7b0d36 --- /dev/null +++ b/docs/src/api/go/example.md @@ -0,0 +1,63 @@ +# Example with Comments + +```go + +// Bring the library into scope with the eduvpn prefix +import eduvpn "github.com/jwijenbergh/eduvpn-common" + +// Callbacks + +func stateCallback(state *eduvpn.VPNState, oldState string, newState string, data string) { + + // OAuth is started, open the browser with the authorization URL + if newState == "OAuth_Started" { + openBrowser(data) + } + + // Multiple profiles are found, we need to send a profile ID back using state.SetProfileID + if newState == "Ask_Profile" { + selectAndSendProfile(state, data) + } +} + +func main() { + // Create the VPNState + state := &eduvpn.VPNState{} + + // Register the state + // We use linux so the client ID will be org.eduvpn.app.linux + // We want to store the config files in configs + // We wrap the callback with the state argument + // And enable debugging + registerErr := state.Register("org.eduvpn.app.linux", "configs", func(old string, new string, data string) { + stateCallback(state, old, new, data) + }, true) + + if registErr != nil { + // handle the error of not being able to register + } + + // Cleanup the library at the end + defer state.Deregister() + + // Connect to an example server without forcing TCP + config, configType, configErr := state.GetConnectConfig("eduvpn.example.com", false) + + if configErr != nil { + // handle the error of not being able to get a config + } + + if configType == "wireguard" { + // Connect using wireguard with the config + } else { + // Connect using OpenVPN with the config + } + + // We are connected + setConnectErr := state.SetConnected() + + if setConnectErr != nil { + // handle the error of not being able to call set connected + } +} +``` diff --git a/docs/src/api/go/functions.md b/docs/src/api/go/functions.md index 0c5faf5..c647787 100644 --- a/docs/src/api/go/functions.md +++ b/docs/src/api/go/functions.md @@ -1 +1,62 @@ # Functions +## Registering +See [Overview](../overview/registering.html) +```go +func Register(name string, directory string, stateCallback func, debug bool) error +``` +- `name`: The name of the client +- `directory`: The directory where the configs and logging should be stored +- `stateCallback`: function with three arguments, full type: + ```go + func(oldState string, newState string, data string) + ``` +- `debug`: Whether or not we want to enable debugging + +Returns an `error` type, nil if no error + +## Discovery +See [Overview](../overview/discovery.html) +```go +func GetDiscoServers() (string, error) +func GetDiscoOrganizations() (string, error) +``` + +Returns a string of JSON data with the servers/organizations and an `error`, nil if no error + +## OpenVPN/Wireguard config +See [Overview](../overview/getconfig.html) +```go +func GetConnectConfig(url string, forceTCP bool) (string, string, error) +``` +- `url`: The url of the server to get a connect config for +- `forceTCP`: Whether or not we want to force enable TCP + +Returns: +- A `string` of the OpenVPN/Wireguard config +- A `string`, `openvpn` or `wireguard` indicating if it is an OpenVPN or Wireguard config +- An `error` (can be nil) + +### Setting a profile ID +```go +func SetProfileID(profileID string) error +``` +- `profileID`: The profile ID to connect to + +Returns an `error`, can be nil indicating no error + +## Connecting/Disconnecting +See [Overview](../overview/connecting.html) +```go +func SetConnected() error +func SetDisconnected() error +``` + +Returns an `error`, can be nil indicating no error + +## Deregister +See [Overview](../overview/deregistering.html) +```go +func Deregister() error +``` + +Returns an `error`, can be nil indicating no error diff --git a/docs/src/api/overview/README.md b/docs/src/api/overview/README.md new file mode 100644 index 0000000..d233b0c --- /dev/null +++ b/docs/src/api/overview/README.md @@ -0,0 +1,8 @@ +# API Overview + +This section defines the API in high-level, we explain what functions there are, what their use is and what a typical flow is for creating an eduVPN client with this library. The language specific documentation will be given in separate sections. + +## Note on types and names +This section acts as an introduction to the API, as such this section will e.g. only give general typing information for the arguments and return values. Please read the language specific API documentation as well. To give an example, we will often say that an `Error` is returned. For Go this is the `error` type, whereas for Python this is simply a string with the error message. + +Additionally, the name of the function described will not be stated exactly as this has language specific differences. For example in Go we use the camel case construct, whereas for python snake case is used. E.g. compare `GetConnectConfig` (Go) and `get_connect_config` (Python) diff --git a/docs/src/api/overview/connecting.md b/docs/src/api/overview/connecting.md new file mode 100644 index 0000000..c2a82a0 --- /dev/null +++ b/docs/src/api/overview/connecting.md @@ -0,0 +1,14 @@ +# Connecting/Disconnecting +## Summary +Name: `Set Connected` and `Set Disconnected` + +Arguments: None + +Returns: `Error` + +Used to signal to the FSM that we're connected/disconnected to the VPN + +## Detailed information +This function is used to set the internal FSM state to connected. As the library does not actually connect to a VPN server, as this is platform specific, this must be called by the client to signal to the library that the user is connected to the VPN. If the FSM does not have a transition to the Connected state it will signal this with a returned error. + +The same function is used to signal the FSM that the VPN is disconnected. diff --git a/docs/src/api/overview/deregistering.md b/docs/src/api/overview/deregistering.md new file mode 100644 index 0000000..0503dbe --- /dev/null +++ b/docs/src/api/overview/deregistering.md @@ -0,0 +1,11 @@ +# Deregistering +## Summary +name: `Deregister` + +Arguments: None + +Returns: Nothing + +Used to cleanup the library by deregistering the client and saving the config files +## Detailed information +The deregister method is used to cleanup the library. It should be called when the client closes. This also saves the state to the directory that was passed in the [Register](./registering.html) method. diff --git a/docs/src/api/overview/discovery.md b/docs/src/api/overview/discovery.md new file mode 100644 index 0000000..0999912 --- /dev/null +++ b/docs/src/api/overview/discovery.md @@ -0,0 +1,63 @@ +# Discovery +## Summary +Name: `Get Disco Servers` and `Get Disco Organizations` + +Arguments: None + +Returns: `JSON string for servers/organizations` and `Error for servers/organizations` + +Note: Depending on the wrapper they may be combined into one function, the return value of this function is then the following: +`organizations, error for organizations, servers, errors for servers` + +Used to obtain the servers and organizations list from the discovery server. +## Detailed information +Discovery is the aspect of eduVPN that allows a client to gather all the servers and organizations it can connect to. For this a discovery server is used, which is registered as `https://disco.eduvpn.org` in the library. We refer to the [official eduVPN documentation](https://github.com/eduvpn/documentation/blob/v3/SERVER_DISCOVERY.md) to learn more about the exact way that these organizations and servers are structured. + +The JSON data that this returns must be used by the client to build an UI. It is common for clients that the discovery functions get called on startup of the client. Note that there can be an error in retrieving the newest version of the servers/organizations. However, this library's goal is to ensure that a version is always available. Thus, a local copy is distributed with this library in the future. + +This library also internally looks at the version of the servers and organizations such that rollbacks attacks are prevented. The client does not have to do any additional checks for this. + +The structure of the JSON data is the structure in the [official eduVPN documentation](https://github.com/eduvpn/documentation/blob/v3/SERVER_DISCOVERY.md) without the `v` (version) field. So, for example, the servers list has a possible JSON structure of this: + +```json +[ + { + "server_type": "institute_access", + "base_url": "https://hku.eduvpn.nl/", + "display_name": { + "en-US": "Utrecht School of the Arts", + "nl-NL": "Hogeschool voor de Kunsten Utrecht" + }, + "keyword_list": "hku" + }, + { + "server_type": "secure_internet", + "base_url": "https://eduvpn.rash.al/", + "country_code": "AL", + "support_contact": [ + "mailto:helpdesk@rash.al" + ] + } +] +``` + +And the organizations list has a possible JSON structure of the following: + +```json +[ + { + "display_name": { + "nl": "SURFnet bv", + "en": "SURFnet bv" + }, + "org_id": "https://idp.surfnet.nl", + "secure_internet_home": "https://nl.eduvpn.org/", + "keyword_list": { + "en": "SURFnet bv SURF konijn surf surfnet powered by", + "nl": "SURFnet bv SURF konijn powered by" + } + } +] +``` + + diff --git a/docs/src/api/overview/flow.md b/docs/src/api/overview/flow.md new file mode 100644 index 0000000..14b5a72 --- /dev/null +++ b/docs/src/api/overview/flow.md @@ -0,0 +1,8 @@ +# Typical flow +A typical flow of creating a client is calling the methods that we talked about in order that we introduced them: + +- The client starts, it registers with the library +- A list of discovery servers/organizations is obtained using the library +- The client selects an URL to connect to and calls the function to get an OpenVPN/Wireguard config from the library +- The client uses the OS specific libraries and programs to use the OpenVPN/Wireguard config to establish a tunnel and calls the function to connect or disconnect +- When the client is done it calls the deregister method to save all configuration and clean up diff --git a/docs/src/api/overview/getconfig.md b/docs/src/api/overview/getconfig.md new file mode 100644 index 0000000..70bcb39 --- /dev/null +++ b/docs/src/api/overview/getconfig.md @@ -0,0 +1,73 @@ +# Getting an OpenVPN/Wireguard config +## Summary +name: `Get Connect Config` + +| Arguments | Description | type | +| --------- | -------------------------------------- | -------- | +| URL | The url of the VPN server to connect to | string | +| Force TCP | Whether or not to force the use of TCP | string | + +Returns: `OpenVPN/Wireguard config (string)` `wireguard/openvpn type (string)`, `Error` + +Used to obtain the OpenVPN/Wireguard config + +## Detailed information + +To get a configuration that is used to actually establish a tunnel with the VPN server, we have the Get Connect Config (the exact name depends on the language you're using) function in the library. This function has two parameters *URL* and *Force TCP*. + +*URL* is the base url of the server to connect to e.g. `nl.eduvpn.org`. Note that this function does not need any further input whether or not we want to connect for institute access or secure internet. This is handled in the library by checking the discovery list. If it does not find the server in the discovery list, it assumes it wants to connect as an institute server. + +The *Force TCP* flag is a boolean that indicates whether or not we want to use TCP to connect over the VPN. This flag is useful if the user has enabled e.g. a setting that forces the use of TCP, which is only supported by OpenVPN. If the Force TCP flag is set to true but the server only supports Wireguard then an error is returned and the config will be empty. + +This function takes care of OAuth which has certain callbacks with data. Additionally, there are also callbacks that need to be registered for selecting the right profile to connect to. These callbacks will be explained now. + +The data that this function returns is the OpenVPN/Wireguard config as a string, the type of config (a string: "wireguard" or "openvpn") and an error if present. + +### Callback: OAuth started + +OAuth has an important callback which is used to obtain the authorization URL by the client. This client needs to open this authorization URL in a web browser such that the user can authenticate with the VPN portal and then authorize the client to obtain OpenVPN/Wireguard configs. + +The callback for this is triggered whenever the OAuth Started state is triggered. The data which this callback has is the authorization url that needs to be opened in the web browser. + +The format of the authorization URL is e.g. this: + +`https://eduvpn.example.com/vpn-user-portal/oauth/authorize?client_id=org.eduvpn.app.linux&code_challenge=DsmGyWFBkvDXiIO33Fs40Z0fn4pxtzDCW2jKvAMptBg&code_challenge_method=S256&redirect_uri=http%3A%2F%2F127.0.0.1%3A8000%2Fcallback&response_type=code&scope=config&state=vha2Krx-HpOyvFkWsWYmey0jrHQ6bnb06PQ6zBXX_bg` + +### Callback: Selecting a profile + +Another aspect that needs to be taken into account is the fact that there can be multiple profiles that a client can connect to. When the function gets called for obtaining an OpenVPN/Wireguard configuration, it asks the client which profile it wants to connect to using the callback that gets triggered on the Ask Profile state. The data is the list of profiles in JSON format, e.g. + +```json +{ + "info": { + "profile_list": [ + { + "profile_id": "internet", + "default_gateway": true, + "display_name": "IPv4 (NAT) IPv6 (GUA) Access", + "vpn_proto_list": [ + "openvpn" + ] + }, + { + "profile_id": "adblock", + "default_gateway": true, + "display_name": "Malware/Tracking-Blocker IPv4 (NAT) IPv6 (GUA)", + "vpn_proto_list": [ + "openvpn" + ] + }, + { + "profile_id": "dnsonly", + "default_gateway": false, + "display_name": "DNS-Only & Malware/Tracking-Blocker (experimental)", + "vpn_proto_list": [ + "openvpn" + ] + } + ] + } +} +``` + +For actually selecting the profile, there is a separate function which takes care of this. This function takes as only argument the profile ID as a string. diff --git a/docs/src/api/overview/registering.md b/docs/src/api/overview/registering.md new file mode 100644 index 0000000..5c40614 --- /dev/null +++ b/docs/src/api/overview/registering.md @@ -0,0 +1,35 @@ +# Registering a client +## Summary +Name: `Register` + +| Arguments | Description | type | +| --------- | -------------------------------------- | -------- | +| Name | Name of the client | string | +| Directory | Path to save logging and state | string | +| Callback | Function to be used as the FSM callback | function | +| Debug | Indicates whether or not to configure debugging capabilities. See [this section](../../../gettingstarted/debugging/index.html) for more information on debugging. | boolean | + +Returns: `Error` + +Used as initialization function of the library +## Detailed information +This library is made to build eduVPN clients. To create such a client, the register method is used. This method takes a *name*, *directory* and *callback*. This method needs to be called whenever a client wants to use this library. If this method is not called then the remaining methods will not be available to use. + +The *name* is the name of the client, also used as a client ID for OAuth. In general the name is the following for each official eduVPN client (documented [here](https://git.sr.ht/~fkooman/vpn-user-portal/tree/v3/item/src/OAuth/ClientDb.php)): + + +| Platform | Client ID | +| -------- | ------------------------ | +| Linux | `org.eduvpn.app.linux` | +| Windows | `org.eduvpn.app.windows` | +| MacOS | `org.eduvpn.app.macos` | +| Android | `org.eduvpn.app.android` | +| iOS | `org.eduvpn.app.ios` | + +The *directory* is the file path where logging and config files are stored. The library creates this directory if it doesn't exist. This can be an absolute or relative path. We recommend to use an absolute path to ensure that the right directory is chosen. + +The *callback* is the function that gets called when the internal Finite State Machine switches state. This callback function must consist of three arguments + +- Old state: The old state as a string, which is the current FSM state before the transition. See [FSM states](../../gettingstarted/debugging/fsm.html#state-explanation) for a list of states. +- New state: The current state for the FSM after the transition, also a string. See [FSM states](../../gettingstarted/debugging/fsm.html#state-explanation) for a list of states. +- Data: The data that gets sent by the library as a string. Most common this is JSON data to build the UI or in case of OAuth it is the authorization URL that needs to be opened by the browser. When there is no data this is an empty string. diff --git a/docs/src/api/python/README.md b/docs/src/api/python/README.md index 452b575..01a14a0 100644 --- a/docs/src/api/python/README.md +++ b/docs/src/api/python/README.md @@ -1 +1,10 @@ -# Go +# Python +As the Go library is build as a *shared* library, it can be loaded by other languages. We have created wrapper code for Python to use this library. We define the functions and then give a similar example to the Go example. + +The functions that we will discuss are all part of the `EduVPN` class defined in eduvpncommon.main. You can import it like so: + +```python +import eduvpncommon.main as eduvpn + +# Then use eduvpn.EduVPN +``` diff --git a/docs/src/api/python/example.md b/docs/src/api/python/example.md new file mode 100644 index 0000000..7c0997f --- /dev/null +++ b/docs/src/api/python/example.md @@ -0,0 +1,48 @@ +# Example with Comments + +```python +import eduvpncommon.main as eduvpn + +# Callbacks +@_eduvpn.event.on("OAuth_Started", eduvpn.StateType.Enter) +def oauth_initialized(url): + # Open the webbrowser with the url + webbrowser.open(url) + + +@_eduvpn.event.on("Ask_Profile", eduvpn.StateType.Enter) +def ask_profile(profiles): + # Set a profile + _eduvpn.set_profile("example") + +# Register the state +# We use linux so the client ID will be org.eduvpn.app.linux +# We want to store the config files in configs +# And enable debugging +_eduvpn = eduvpn.EduVPN("org.eduvpn.app.linux", "configs") +register_err = _eduvpn.register(debug=True) + +if register_err: + # Handle error + +# Connect to eduvpn.example.com +config, config_type, config_err = _eduvpn.get_connect_config("eduvpn.example.com", False) + +if config_err: + # Handle error + +if config_type == "wireguard": + # Connect using wireguard with the config +elif config_type == "openvpn": + # Connect using OpenVPN with the config +else: + # Handle error + +# Set connected +set_connect_err = _eduvpn.set_connected() +if set_connect_err: + # Handle error + +# Handle cleanup +_eduvpn.deregister() +``` diff --git a/docs/src/api/python/functions.md b/docs/src/api/python/functions.md index 0c5faf5..ebfb774 100644 --- a/docs/src/api/python/functions.md +++ b/docs/src/api/python/functions.md @@ -1 +1,70 @@ # Functions +## Creating the class +See [Overview](../overview/registering.html) + +This creates the class and basically forwards these arguments when `register` is called. +```python +def __init__(self, name: str, directory: str) +``` +- `name`: The name of the client +- `directory`: The directory where the configs and logging should be stored + +## Registering +See [Overview](../overview/registering.html) +```python +def register(self, debug=False: bool) -> Optional[str] +``` +- `debug`: Whether or not we want to enable debugging + +Returns an optional `string` for the error message + +## Discovery +See [Overview](../overview/discovery.html) +```python +def get_disco_servers(self) -> (Optional[str], Optional[str]) +``` +```python +def get_disco_organizations(self) -> (Optional[str], Optional[str]) +``` + +Returns an optional `string` of JSON data with the servers/organizations and an optional error message + +## OpenVPN/Wireguard config +See [Overview](../overview/getconfig.html) +```python +def get_connect_config(self, url: str, forceTCP: bool) -> (Optional[str], Optional[str], Optional[str]) +``` +- `url`: The url of the server to get a connect config for +- `forceTCP`: Whether or not we want to force enable TCP + +Returns: +- An optional `string` of the OpenVPN/Wireguard config +- An optional `string`, `openvpn` or `wireguard` indicating if it is an OpenVPN or Wireguard config +- An optional error message `string` + +### Setting a profile ID +```python +def set_profile(self, profile_id: str) -> Optional[str] +``` +- `profile_id`: The profile ID to connect to + +Returns an optional `string`, which is the error message + +## Connecting/Disconnecting +See [Overview](../overview/connecting.html) +```python +def set_connected(self) -> Optional[str] +``` +```python +def set_disconnected(self) -> Optional[str] +``` + +Returns an optional `string`, which is the error message + +## Deregister +See [Overview](../overview/deregistering.html) +```python +def deregister() -> Optional[str] +``` + +Returns an optional `string`, which is the error message |
