GithubHelp home page GithubHelp logo

eduvpn / eduvpn-common Goto Github PK

View Code? Open in Web Editor NEW
4.0 4.0 3.0 5.73 MB

Code to be shared between eduVPN clients

License: MIT License

Shell 4.61% Python 12.88% Go 81.23% Makefile 0.55% Batchfile 0.27% Dockerfile 0.46%

eduvpn-common's People

Contributors

jwijenbergh avatar peske avatar rozmansi avatar stevenwdv avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

eduvpn-common's Issues

V2: Should ExpiryTimes be integrated into CurrentServer

Right now ExpiryTimes is a separate function.

Should this be integrated into the data when the current server is obtained or should this be integrated into the configuration data?

It's not really nice that this is returned in the VPN configuration data as clients can start by having a VPN already connected (e.g. Linux), they would then not be able to query this data if ExpiryTimes is removed

V2: Should discovery have a `local` argument to force the cache?

Problem:

getting disco servers/organizations can be slow due to the discovery server or the users network being slow. Even though we have a timeout and a cookie, it might be nice to introduce a local/cache argument to the functions

If non-zero/true this means that only the cached copy is returned. Clients can thus first call the functions with true and then asynchronously call it with false to get the most up to date copy.

This is right now the most problematic on startup where clients have no discovery cache filled

V2: Combine discovery functions

Should DiscoOrganizations and DiscoServers be combined? Why are there 2 functions?

Clients should almost always fetch them together, no?

Suspicious error handling

I have to tell that I'm not absolutely sure about this issue, just sharing the first intuition. I will have to take more detailed look.

It looks to me that error handling is convoluted because a lot of error wrappings that happen throughout the code. Catching error, than wrap it and return the wrapped, than maybe wrap it again, etc. Again, will have to take a deeper look into this problem.

Another thing that bit scares me is the fact that errors are kinda propagated to UI. Yes, I agree that it is reasonable to have a meaningful error message in the UI. But sending a whole error structure bit scares me cause it looks like passing error handling upstream to UI.

typedef struct error {

Not sure what's the reason for wrapping, but if it is to get the stack trace - this already exists in errors package out-of-the-box.

When it comes to passing error messages to UI, I would rather go with error codes. This way UI can do some translation / localization...

Again, will have to take a deeper look to have more articulate suggestion.

Coding guidelines are not followed

Although not being a critical, functional problem, not following coding guidelines causes problem on a long run, when the code should be maintained, especially when a new developers are included. For this reason I strongly suggest taking much more care about that. In the current code almost all the guidelines are broken.

Let me first share few authoritative resources for learning more about the guidelines:

Also, I would strongly suggest using linters, formaters, and for developers who are new in the language some IDE that helps with that. For example, JetBrains GoLand will report hundreds problems with the current code. Similar probably stands for Visual Studio Code with an appropriate plugin.

Current code contains dozens of guideline problems in any file. Let me share just few:

func test_connect_oauth_parameter(

Test functions should start with Test followed by method name. For example, if we want to test function called MyFunction, we will create test TestMyFunction. Snake case (like test_connect_oauth_parameter) is never used in Go, not for function names, nor for anything else. Camel case should be used instead. Camel case is often used in the current code.

oauth := currentServer.GetOAuth()

Variable names should not ever collide with already used names. Here we have variable oauth that collides with package name oauth.

Documentation comments almost never follow the guidelines https://go.dev/doc/comment

These are only few examples that often happen.

Persist internal state regularly

Unregistering engine saves the internal state (user settings). Unregister is called when client is terminating. However, client might be terminated by force. We had this problem with Windows client: manually installing newer version of the client kills all running client processes and user changes are lost.

If eduvpn-common doesn't implement in-between saves, we will experience this issue again.

In .NET this was fixed by introducing a timer which is reset to 5 seconds on each settings change. When timer triggers, settings are saved.

See: Amebis/eduVPN#222

Register: Do not contact discovery

When register is called discovery MUST NOT be called. https://github.com/eduvpn/eduvpn-common/blob/main/client/client.go#L197-L204

Only do this when getting a config or the application requests discovery. When getting the server list this should maybe not be called, but eduvpn-common might need to have a separate function e.g. "get_delisted_servers" that returns which current servers are delisted. This way the server list can load as fast as possible and the application can asynchronously update the delisted servers with a warning symbol

Receiver arguments not consistent

Receiver functions of the same type should have consistent receiver argument types. For example, if we have one function with receiver argument client *Client (note pointer type), like in:

func (client *Client) handleError(message string, err error) error {

then it should not have a function with receiver argument client Client (note value type), like in:

func (client Client) isLetsConnect() bool {

In my experience, for structure types it is almost always better to have pointer receivers than value receivers.

OAuth implementation - Important

The key thing that I don't like here is decision to give up on the existing package and develop one from the scratch. I really don't like this. Especially since we are talking about package from the official Google repo, meaning very reliable source. And also especially because it is security-related part.

So I would strongly suggest going with the existing package. If the existing package does not implement everything that we need, we can extend it. So my suggestion is to do the following:

  • Fork the official package repo
  • Implement the feature(s) we are missing in a meaningful way, to fit the existing package design decisions.
  • Create a PR upstream, in the official repo, and offer our extension
  • Use forked version in eduvpn project until our PR isn't accepted.
  • Switch to the official repo as soon as they accept our PR

The key benefits of such approach are:

  • We don't have to worry about maintaining the code. Very reliable and knowledgeable people will do that for us, for free.
  • Top-notch pros will deal with this security related piece, and we don't have to worry about that.
  • If we make PR for them, we will get instant review of our code by top-notch engineers for free.

I'm not sure what feature is missing in the official package? I see that PKCE is implemented in golang/oauth2@fd043fe . @jwijenbergh can you please explain?

Update error AUR

I am not sure if you also have encountered my same issue but I am getting an error trying to update with yay on ArchLinux:

curl https://app.eduvpn.org/linux/v4/deb/[email protected] | gpg --import
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   449  100   449    0     0   1966      0 --:--:-- --:--:-- --:--:--  1969
gpg: key 02BB8048BBFF222C: "eduVPN Linux App Repository Signing Key <[email protected]>" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
❯ yay -S python-eduvpn-client
AUR Explicit (1): python-eduvpn-client-4.2.1-1
AUR Dependency (1): python-eduvpn_common-1.2.0-1
:: PKGBUILD up to date, skipping download: python-eduvpn-client
:: PKGBUILD up to date, skipping download: python-eduvpn_common
  2 python-eduvpn-client             (Build Files Exist)
  1 python-eduvpn_common             (Build Files Exist)
==> Packages to cleanBuild?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> 
  2 python-eduvpn_common             (Build Files Exist)
  1 python-eduvpn-client             (Build Files Exist)
==> Diffs to show?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> 
==> Making package: python-eduvpn-client 4.2.1-1 (Wed 28 Feb 2024 05:05:54 PM CET)
==> Retrieving sources...
  -> Found python-eduvpn-client-4.2.1.tar.xz
  -> Found python-eduvpn-client-4.2.1.tar.xz.asc
==> WARNING: Skipping verification of source file PGP signatures.
==> Validating source files with sha256sums...
    python-eduvpn-client-4.2.1.tar.xz ... Passed
    python-eduvpn-client-4.2.1.tar.xz.asc ... Skipped
==> Making package: python-eduvpn_common 1.2.0-1 (Wed 28 Feb 2024 05:05:55 PM CET)
==> Retrieving sources...
  -> Found eduvpn-common-1.2.0.tar.xz
  -> Found eduvpn-common-1.2.0.tar.xz.asc
==> WARNING: Skipping verification of source file PGP signatures.
==> Validating source files with sha256sums...
    eduvpn-common-1.2.0.tar.xz ... Passed
    eduvpn-common-1.2.0.tar.xz.asc ... Skipped
:: (1/2) Parsing SRCINFO: python-eduvpn-client
:: (2/2) Parsing SRCINFO: python-eduvpn_common
pub   ed25519 2023-03-01 [SC] [expires: 2033-02-26]
      227FF3F8F829D9A9314D9EBA02BB8048BBFF222C
uid           [ unknown] eduVPN Linux App Repository Signing Key <[email protected]>

pub   ed25519 2023-03-01 [SC] [expires: 2033-02-26]
      227FF3F8F829D9A9314D9EBA02BB8048BBFF222C
uid           [ unknown] eduVPN Linux App Repository Signing Key <[email protected]>

==> Making package: python-eduvpn_common 1.2.0-1 (Wed 28 Feb 2024 05:05:56 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Found eduvpn-common-1.2.0.tar.xz
  -> Found eduvpn-common-1.2.0.tar.xz.asc
==> Validating source files with sha256sums...
    eduvpn-common-1.2.0.tar.xz ... Passed
    eduvpn-common-1.2.0.tar.xz.asc ... Skipped
==> Verifying source file signatures with gpg...
    eduvpn-common-1.2.0.tar.xz ... Passed
==> Removing existing $srcdir/ directory...
==> Extracting sources...
  -> Extracting eduvpn-common-1.2.0.tar.xz with bsdtar
==> Sources are ready.
==> Making package: python-eduvpn_common 1.2.0-1 (Wed 28 Feb 2024 05:05:58 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> WARNING: Using existing $srcdir/ tree
==> Removing existing $pkgdir/ directory...
==> Starting build()...
make -C exports
make[1]: Entering directory '/home/pietro/.cache/yay/python-eduvpn_common/src/eduvpn-common-1.2.0/exports'
CGO_ENABLED=1 go build -o lib/linux/amd64/libeduvpn_common-1.2.0.so -buildmode=c-shared .
disco.go:45:2: cannot find package "github.com/eduvpn/eduvpn-common/client" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/client (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/client (from $GOPATH)
exports.go:46:2: cannot find package "github.com/eduvpn/eduvpn-common/internal/log" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/internal/log (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/internal/log (from $GOPATH)
exports.go:47:2: cannot find package "github.com/eduvpn/eduvpn-common/internal/oauth" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/internal/oauth (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/internal/oauth (from $GOPATH)
exports.go:48:2: cannot find package "github.com/eduvpn/eduvpn-common/internal/server" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/internal/server (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/internal/server (from $GOPATH)
disco.go:46:2: cannot find package "github.com/eduvpn/eduvpn-common/types" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/types (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/types (from $GOPATH)
exports.go:49:2: cannot find package "github.com/go-errors/errors" in any of:
        /usr/lib/go/src/github.com/go-errors/errors (from $GOROOT)
        /home/pietro/go/src/github.com/go-errors/errors (from $GOPATH)
make[1]: *** [Makefile:20: lib/linux/amd64/libeduvpn_common-1.2.0.so] Error 1
make[1]: Leaving directory '/home/pietro/.cache/yay/python-eduvpn_common/src/eduvpn-common-1.2.0/exports'
make: *** [Makefile:4: build] Error 2
==> ERROR: A failure occurred in build().
    Aborting...
 -> Failed to install layer, rolling up to next layer.error:error making: python-eduvpn_common - exit status 4
==> Making package: python-eduvpn-client 4.2.1-1 (Wed 28 Feb 2024 05:05:59 PM CET)
==> Checking runtime dependencies...
==> Missing dependencies:
  -> python-eduvpn_common>=1.1.0
==> Checking buildtime dependencies...
==> ERROR: Could not resolve all dependencies.
 -> error making: python-eduvpn-client-exit status 8
==> Making package: python-eduvpn_common 1.2.0-1 (Wed 28 Feb 2024 05:06:00 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Found eduvpn-common-1.2.0.tar.xz
  -> Found eduvpn-common-1.2.0.tar.xz.asc
==> Validating source files with sha256sums...
    eduvpn-common-1.2.0.tar.xz ... Passed
    eduvpn-common-1.2.0.tar.xz.asc ... Skipped
==> Verifying source file signatures with gpg...
    eduvpn-common-1.2.0.tar.xz ... Passed
==> Removing existing $srcdir/ directory...
==> Extracting sources...
  -> Extracting eduvpn-common-1.2.0.tar.xz with bsdtar
==> Sources are ready.
==> Making package: python-eduvpn_common 1.2.0-1 (Wed 28 Feb 2024 05:06:02 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> WARNING: Using existing $srcdir/ tree
==> Removing existing $pkgdir/ directory...
==> Starting build()...
make -C exports
make[1]: Entering directory '/home/pietro/.cache/yay/python-eduvpn_common/src/eduvpn-common-1.2.0/exports'
CGO_ENABLED=1 go build -o lib/linux/amd64/libeduvpn_common-1.2.0.so -buildmode=c-shared .
disco.go:45:2: cannot find package "github.com/eduvpn/eduvpn-common/client" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/client (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/client (from $GOPATH)
exports.go:46:2: cannot find package "github.com/eduvpn/eduvpn-common/internal/log" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/internal/log (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/internal/log (from $GOPATH)
exports.go:47:2: cannot find package "github.com/eduvpn/eduvpn-common/internal/oauth" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/internal/oauth (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/internal/oauth (from $GOPATH)
exports.go:48:2: cannot find package "github.com/eduvpn/eduvpn-common/internal/server" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/internal/server (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/internal/server (from $GOPATH)
disco.go:46:2: cannot find package "github.com/eduvpn/eduvpn-common/types" in any of:
        /usr/lib/go/src/github.com/eduvpn/eduvpn-common/types (from $GOROOT)
        /home/pietro/go/src/github.com/eduvpn/eduvpn-common/types (from $GOPATH)
exports.go:49:2: cannot find package "github.com/go-errors/errors" in any of:
        /usr/lib/go/src/github.com/go-errors/errors (from $GOROOT)
        /home/pietro/go/src/github.com/go-errors/errors (from $GOPATH)
make[1]: *** [Makefile:20: lib/linux/amd64/libeduvpn_common-1.2.0.so] Error 1
make[1]: Leaving directory '/home/pietro/.cache/yay/python-eduvpn_common/src/eduvpn-common-1.2.0/exports'
make: *** [Makefile:4: build] Error 2
==> ERROR: A failure occurred in build().
    Aborting...
 -> error making: python-eduvpn_common-exit status 4
 -> Failed to install the following packages. Manual intervention is required:
python-eduvpn-client - exit status 8
python-eduvpn_common - exit status 4

V2: possible logging approaches

Two options for logging

  • Should we expose a Go function that Logs
    • Pros: Produces uniform logging
    • Cons: Client needs an indirection step to call Go just if it wants to log client specific things
  • Should the client register a logging callback/interface?
    from: @rozmansi
    Pros: No indirection step for client specific logging
    Cons: Logging would not be uniform

V2: Should CurrentServer be returned on GotConfig?

Should the current server be sent as data to the GotConfig state?

Upside:

  • Not as much calls needed to currentserver anymore
  • The FSM becomes the best single source of truth for the current state

Downside:

  • Performance maybe? As clients that not want to use this data then have extra (very small though) overhead

V2: Possible pre-provisioned server list approaches

This concerns the servers that should be added, so no discovery, purely the internal eduvpn-common server list

  • A function that adds a server without triggering callbacks?
    OR:
  • Handle pre-provisioning in eduvpn-common e.g. "preconfig_windows.go", "preconfig_macos.go", "preconfig_linux.go"
    • Upside: It becomes very easy for clients
    • Downside: OS specific functionality

Something else maybe?

Development PGP key invalid

The development key in keys/[email protected] cannot be parsed by recent GnuPG

$ cat /usr/share/openpgp-keys/eduvpn-dev.asc
----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEZTkiAhYJKwYBBAHaRw8BAQdAdREDbNbEDNvOtNxwcwFLoaAOhdwJSkpddxn4
qniBqee0RWVkdVZQTiBMaW51eCBEZXYgQXBwIFJlcG9zaXRvcnkgU2lnbmluZyBL
ZXkgPGFwcCtsaW51eCtkZXZAZWR1dnBuLm9yZ4iZBBMWCgBBFiEEenPWKtDwhFca
Mslg1XEEv5siPL8FAmU5IgICGwMFCRLMAwAFCwkIBwICIgIGFQoJCAsCBBYCAwEC
HgcCF4AACgkQ1XEEv5siPL/rrgD/caiME81fUtpqCnKgGXD2ntAg2M2mSpk7IfHe
J/Ih1bgA/i3uQOWFhur1r3I1ufxaaS0YjIIMZisSugTc5cWJ0isC
=orU4
-----END PGP PUBLIC KEY BLOCK-----
$ LANG=C gpg /usr/share/openpgp-keys/eduvpn-dev.asc
gpg: WARNING: no command supplied.  Trying to guess what you mean ...
gpg: no valid OpenPGP data found.
gpg: processing message failed: Unknown system error

I am using the most recent version of GnuPG.

$ LANG=C gpg --version
gpg (GnuPG) 2.4.4
libgcrypt 1.10.3-unknown
Copyright (C) 2024 g10 Code GmbH
License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Many distributions use GnuPG to verify signatures. So this issue effectively prevents me from distributing this version for Gentoo Linux. I am unsure if it's a bug in GnuPG as Sequoia reads the key.

$ sq inspect /usr/share/openpgp-keys/eduvpn-dev.asc
/usr/share/openpgp-keys/eduvpn-dev.asc: OpenPGP Certificate.

    Fingerprint: 7A73D62AD0F084571A32C960D57104BF9B223CBF
Public-key algo: EdDSA
Public-key size: 256 bits
  Creation time: 2023-10-25 14:11:14 UTC
Expiration time: 2033-10-22 14:11:14 UTC (creation time + 9years 11months 27days 21h 50m 24s)
      Key flags: certification, signing

         UserID: eduVPN Linux Dev App Repository Signing Key <[email protected]

Can you please check your key generation routine first for some uncommon key parameters?

Client implementation accross files

As far as I can see, Client structure is implemented in https://github.com/eduvpn/eduvpn-common/blob/main/client/client.go . Many of its receiver functions (methods) are also implemented there. But for some reason there are few receiver functions implemented in https://github.com/eduvpn/eduvpn-common/blob/main/client/fsm.go . For example:

func (client *Client) SetSearchServer() error {

It is a bad practice to define receiver functions of the same type in multiple files. Is there any reason for such implementation?

PGP public key?

Hi, I've packaged this for ArchLinux and noticed that the PGP detached signature for the release 1.0.0 uses a public key (0x02BB8048BBFF222C) that isn't published on the major key servers. Is the public key located somewhere public? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.