Giter VIP home page Giter VIP logo

trivrost's Introduction

trivrost

trivrost

Test Renovate Depenabot CII Best Practices

forthebadge forthebadge

trivrost is a repurposable application-downloader and -launcher in the form of a native executable: it updates some files on a computer and executes a command afterwards, no questions asked. It can also update itself to introduce new features without the need for user interaction. One possible use case could be keeping an application (e.g. JARs) and its runtime (e.g. JRE) up to date without any additional client-side requirements. See reasons.md for more background information.

When do I need trivrost?

When you need to deploy an always-online desktop application which always needs to be up to date to many users using all three major OSs and all of them expect your software to just work.

What does it look like?

Screenshot of trivrost progress window under Windows

How does it work?

You release your own build of a trivrost executable to your users. The users start it, causing it to install and run your software by downloading required files from a webserver administrated by you.

State of this project

Production-ready, with high confidence for Linux and Windows builds. Has approximately 10.000 active Windows users for one of our builds. MacOS-support needs input.

Learn more

  1. Background info
  2. Glossary
  3. How to use trivrost (Start here)
  4. Lifecycle
  5. File locations
  6. Building
  7. Launcher-config specification
  8. Deployment-config specification
  9. Bundle info specification
  10. Security
  11. Command line reference
  12. Troubleshooting

Contribute to development

See CONTRIBUTING.md.

trivrost's People

Contributors

blexsetlog avatar dchaykin avatar dependabot[bot] avatar dragetd avatar drrdietrich avatar ma-assbrock avatar mend-bolt-for-github[bot] avatar mmulthaupt avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

trivrost's Issues

Allow client-authentication to limit who downloads the software

Is your feature request related to a problem? Please describe.
We received external input, that one use-case would be to limit who is able to access the URLs and not let everyone download the software.

Describe the solution you'd like
Discuss some possibilities to limit the client access.

Describe alternatives you've considered
One of our benefits (which we should document!) is, that our update-server only requires to be a "simple" HTTP server. This means we should not rely on custom server code but stick to HTTP semantics that can be configured with common webservers.

Alternative 1: Client Basic Auth
Relatively easy to use in go (https://golang.org/pkg/net/http/#Request.BasicAuth). The client would need to provide a username and password.
This could be as simple as a default-password that is baked into the client (launcher-config) and prevents access from third-parties who never got the launcher. Of course, once the password is 'leaked', it provides no more protection. This is not a very secure scheme for anything, but also simple to implement.

Per-client passwords would require some kind of backend or infrastructure to manage these. Sounds a bit out of scope for trivrost, but I am open for ideas.

ENFORCES HTTPS.

Alternative 2: Client certificates
Client certificates are a kind of individual client credentials, but allow generating these and providing trust though a CA. It they are signed by the CA, they are trusted and no more backend-logic is needed. Still ,each client would need its own cert. Not sure how this would be done.

Implementing it in go is a little more tedious (= error prone) (https://gist.github.com/michaljemala/d6f4e01c4834bf47a9c4), but possible.

Alternative 3: Identify clients but local client data
Some sort of hash from MAC, serial numbers and whatnot… no idea how exactly it would look like, but I already know this is simple security by obscurity and even more stupid that alternative 1. But again, better than nothing.

Open for more ideas.

Eliminate all silent failure scenarios

Is your feature request related to a problem? Please describe.
If, for whatever reason, trivrost terminates before opening a log file, no log output can be seen on Windows, because we build trivrost as a GUI binary (which is a Windows formalism for GUI applications to prevent a console window from spawning, but has the side-effect of causing standard streams to be unlinked from the console if it was started from one). While we currently allow building the project with the TRIVROST_FORCECONSOLE environment variable set to always show the console, this binary is not readily available on client machines in the moment a problem appears.

Describe the solution you'd like
Any fatal errors requiring program termination should be deferred until the GUI is ready, and be displayed there on top of being logged. Then, we will be forced to fail silently on Windows only if both GUI and logging initialization fail.

Describe alternatives you've considered
We could allow to transmit all logs to a server, but this has huge data privacy implications and can also fail if the connection fails for some reason.

Productname not set correctly for 'example company' in AppLocker

Windows is reading infos from the signature metadata. But somehow, now everything from SignTool is propagated correctly:

image

This is from the AppLocker dialog which allows creating rules based on signatures. Moving the slider upwards replaced the fields with wildcards (*) and thus allows how broadly the rule applies.
With a correct product name this would be a bit more pretty.

We tried passing it via /n of the signtool, assuming what AppLocker shows is related to the certificate. It is unclear if it is the certificate or the versioninfo metadata. We set the versioninfo metadata and it is visible under file properties, but not in Applocker.

Documentation needs work

Our documentation still has an air of proprietariness around it, and is very low quality in places. It needs to be worked on.

Implement tests for hasher

The hasher should be able to handle files, hidden files, symlinks to files, symlinks to directories, invalid symlinks and should react accordingly to specifications. This specification should also be documented.

Self-update: Cannot move binary under certain conditions

The following problem was found occurring in the wild.

P Could not rename running binary. [godown/bundle/update_self.go:(*Updater)():103] err=rename F:\Application Data\Setlog\***\***.exe F:\Application Data\Setlog\***\~***.old.f556990e1e510594: The process cannot access the file because it is being used by another process., localBinaryPath=F:\Application Data\Setlog\***\***.exe, oldBinaryNewPath=F:\Application Data\Setlog\***\~***.exe.old.f556990e1e510594

This could be caused by pretty much anything. Anti-virus and dodgy security software comes to mind. Failing hard is never a good reaction. How should we deal with cases such as this?

Add option to skip always-online behavior

Now that we are open source, an obvious use case one might have is for trivrost to skip updates when no connection can be made. This allows for offline execution of applications which do not require to have a connection.

Linux: `Run In Konsole` does not work

It was reported by Martin before:

When starting trivrost with 'run in Konsole', trivrost fails to restart itself and freezes somewhere in RestartWithBinary(). ps -aux shows the konsole process with trivrost as the commandline argument, but not trivrost itself.

martin@mmul:~$ ps -aux | grep osca
martin    1844  2.5  0.3 749592 64408 ?        Sl   12:06   0:00 /usr/bin/konsole --hold -e /home/martin/Downloads/xxx

It is not fully clear, what is happening there.

Integration testing

Now that we are open source, we can use services such as AppVeyor for platform-specific integration tests.

Use Pull-Requests for releases through master

Thinking about our releasing process, as soon as we have a pipeline anymore (#47), a release on master must always run successfully through the pipeline.

Since this should be the case on develop, it should always be the case on master when doing a release. Unless we mess up and accidentally merge the wrong commits, which can happen in the CLI. So my idea I got from another team: We could use PRs also to merge into master. This would allow even others to comment and check the pipeline via GitHub and make the release more straight-forward.

Of course, when using development as the branch to base the PR on, an 'accidental' commit on develop could end up in the release during the PR is open. The chance of this happening with our workflow or even if, then causing a problem, is extremely minimal.

What are you thoughts?

Document installdown

While anyone who is only interested in building the project with the provided Makefile does not strictly need to be aware of the tools under cmd, these should still be documented somehow.

launcher-config: `BinaryName` should be called `ProgramName`

For MacOS, BinaryName specifies the name of the application bundle, followed by .app. This is a special, executable folder: it definitely is not a binary in or of itself. A better name for BinaryName would be ProgramName. This would make it consistent with the term ProgramPath in the code.

Provide mechanism to reduce repetitions in deployment-config

In a typical deployment-config, the same URL is repeated a lot of times. Also Execution.Commands.Arguments calls for a lot of copy-pasta if many arguments are required. YAML has anchors to help alleviate the issue; JSON – which we currently use – has nothing comparable. It would be nice to find a backwards-compatible way to support more DRY config files without bloating our code base.

Enable releaseing of -rc* or -beta versions

We would like to be able to release -rc* versions. The version-string is parsed at a few places and we need to check, if it would cause any problem to use tags with such extra version info appended.

Validator: Check if application executable will be downloaded

Validator checks if application executables can be downloaded, but not if they will actually be downloaded when trivrost is started. This can cause problems e.g. when Execution is configured to launch the same binary for both windows-386 and windows-amd64, but only one of them is configured to download the bundle containing the file.

Example deployment-config snippet (will cause missing file myapp\myapp.exe on 32 bit Windows):

    "Bundles": [
        {
            "BundleInfoURL": "https://example.com/myapp/bundleinfo.json",
            "LocalDirectory": "myapp",
            "TargetPlatforms": [ "windows-amd64" ]
        }
    ],
    "Execution": {
        "Commands": [
            {
                "Name": "myapp\\myapp.exe",
                "TargetPlatforms": [ "windows" ]
            }
        ]
    }

Use GitHub pages

Have a simple website with our logo and a simple pitch what the project is about. A static website generator should do.

Depends on #37 :-)

GUI: Don't jump to front if previous instance was minimized

Currently, all windows spawned by trivrost will be centered and jump to the front without taking focus. While this is ideal when first starting the application, it can bring frustration when it restarts multiple times. We can supply a flag -minimized on restarting if the user minimized the window, so the restarting instance will continue quietly as well.

Rethink the process of creating MSI bundles

There are a bunch of things bothering me:

Using a go utility, not compiled but called like a script with a go runtime from a unix makefile to create an installed script for windows used by a windows tool to create an msi installer. 🤦‍♂️

Thing is: I do not know how exactly to simplify things.

Suggestions of the top of my mind:

  • Stop using go-tools like scripts. Expect compiled versions in PATH and compile the tools before using them (or have them in the docker image)
  • Maybe some replacements could be even done from within the WIX XML files. It is a powerful tool with turing-complete Syntax. On the other hand, parsing a json from an XML sounds even more crazy. Maybe we do need a go utility… but instead of generating the XML files it sets env vars and the xml files use these? I am not sure.

All in all, this is all on the 'but it works and what you say sounds like a lot of work'-side of things. But it is defiantly something on our list of technical dept.

I'll move it to future at least, because things are kind of already 'out there' anyways.

System-mode installations should ignore system-bundle updates under certain conditions

Using the msi-based system-mode installation, an update to a system-bundle forces the user currently to reinstall the MSI with admin privileges.

The whole idea behind the MSI installer is to provide a solution for very restrictive environments. And requiring the admin to update the software immediately - otherwise it will not start - is not the nicest solution.

Current idea: Allow system-mode bundles to be outdated as long as the other bundles are up to date.
The reasoning is, that the system-mode bundles are usually the JRE and the other bundles are the application that is deployed.

More log output (starting and restarting)

Describe the bug
If trivrost is started with incorrect parameters, it does not log anything. Shortly before restarting after a self-update, it would be also good to have a log-output.

Document validator

We developed the validator tool (cmd/validator) to report errors in a deployment-config as well as inconsistencies between a deployment-config and what's actually available under the configured URLs. We should document how and when to use it.

New signer implemented in go does not read key files

Describe the bug
The signer implemented with #44 does not read the private key when it is put into a file. It says
Fatal: Could not parse the private key: x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)

To Reproduce
Save the private key to a file.crt and use signer file.crt bundleinfo.json

The old signer script works in that case.

Logging of the output of executed command

The output of the executed command is not saved anywhere. This is non-trivial since trivrost quits after executing, and I'd like to keep it that way.

But I want to suggest a workaround we might want to discuss:
We could allow executing things in a shell. trivrost would need to implement it for linux/mac (bash -c or sh -c) and windows (cmd.exe) and run the command via the shell.
This might have implications about the visible windows and such. But would allow us to use food.exe 2> out.err for example to redirect stderr to a file. We could hide this feature behind an option in trivrost and trivrost could automatically replace out.err by its actual logfile (and use >> to append).

It could be:

"Commands": [
    {
        "Name": "/bin/bash",
        "Arguments": [ "-c", "java/bin/java -jar foo.jar >> $LAUNCHERLOGFILE" ],
        "TargetPlatforms": [ "linux" ]
    },
]

where , but yes, this would be the hack.

I do not really like it myself. Just thought I'd put this up for discussion.

Build pipeline for build-testing

After moving to GitHub, we ditched our existing pipeline configuration. This needs to be re-created with building under all the OS system and running the different tests.

I will try doing this with GitHub Actions.

Files mentioned in file_locations.md out of date

The locking mechanism has changed slightly over the past. file_locations.md should mention the existence of the .lock file, which is actually locked using OS APIs, guarding all other files.

Current timestamp security mechanism is broken

Currently, we implemented the timestamp mechanism to prevent downgrade-attacks on bundles. The timestamp is unique per bundle-name tho. Nothing prevents an attack from downgrading a client to another signed but older (and vulnerable) bundle (e.g. for jre versions: downgrade from amazon-corretto-8u222 to adopenopenjdk-8u202).

This scenario is only relevant if the attacker is already able to MITM the connection. In a second step the attack would need a local attack vector against the application, since this is the only thing depending on the downgraded bundle.
This is a pretty low-risk scenario.

And we have decided to never change bundles anyways. A new version of a bundle is a new bundlename. In that case, we do not even need this functionality at all.

I suggest removing it.

Taskbar: Group entries

Currently, multiple launches of the application started by trivrost are not grouped in the taskbar. Java Web Start does this somehow. The question is whether this is actually wanted. As far as I know, the user can neither detach task bar entries from a task bar group, nor change the order of the tasks within the group. I remember times with other applications where I have been annoyed by being unable to change the order, and thus vote for not pursuing this any further.

Remove error dialog.

While some problems require the user to take action, failing hard is still bad UX. This issue serves as a collection point for all conceivable instances in which trivrost still shows an error dialog:

  • Any kind of file IO error occurs
    • File locked (e.g. #22)
    • Missing permissions
    • Not enough disk space
    • Other problems
  • SHA-mismatch
  • Signature-mismatch
  • Deployment-config or Bundle info Timestamp is older than most recent one
  • Content-Length of a download changes between (range) requests
  • Starting a command fails (e.g. #25) (Fixed by #71)

To fix this we need a slightly more sophisticated way to display the current status to the user. What we currently have caters a lot to how the Download type reports state.

We probably won't actually eliminate the error dialog entirely. For example, the behavior to show possible command line arguments on Windows when a bad argument was provided (#73) is quite useful.

Document installdown

The helper utility is used in the MSI bundling process. It should be documented in some way in the docs.

MacOS: Program lifecycle indeterminate

MacOS has no such thing as a Start Menu. As such there is no suitable place for a shortcut with the -uninstall flag – which is needed to remove trivrost and bundles from the drive – to reside. In theory, on MacOS, you delete an application by deleting its .app bundle folder. However, since the primary focus of the project was to support Windows with its %APPDATA% and %LOCALAPPDATA% principle, on MacOS the .app, downloaded bundles and lock-files lie next to each other under $HOME/Library/Application Support/<Vendor Name>/<Product Name>/. To make matters worse, there is Gatekeeper Path Randomization, which will move an application started from the Downloads folder within Finder to an isolated, read-only environment, before running it. The path looks something like this:
/private/var/folders/sw/gd3tm0bs6bx8wt_j_8337ks40000gn/T/AppTranslocation/8EADD785-0DAD-4752-978A-1E9DD5172B5F/d/***.app/Contents/MacOS/launcher

Generally we feel that we are lacking knowledge about MacOS in order to attempt to make improvements to the current behavior. Any additional information will be helpful.

Need sensible directive for when to `panic()` and when to just return an `error`

At the moment, it is not clear when to panic() and when to return an error to inform the caller of a problem. We should expand on this in our documentation. Generally, we panic() whenever there is no good way to deal with a problem, and trivrost should stop what it is doing. However, we also often panic to avoid the hassle of checking for the returned error, as indicated by the abundance of MustXXX()-functions.

Document maintenance scheme

We do no longer maintain v1.0.x, v1.1.x and v1.2.x on GitHub.

But we promise compatibility between all v1.x versions. We should document this.

Phase out global state which needs initialization

Packages places and system contain global state which needs initialization. If initialization should ever fail to precede attempts to read it, hard to debug situations can arise. This should be refactored accordingly.

Gtk-Warning in gui.go

Upon calling ui.Main() in gui.go:

(process:6349): Gtk-WARNING **: Locale not supported by C library.
        Using the fallback 'C' locale.

Seen on Linux when starting from console.

"The handle is invalid"

The following was witnessed occurring once for no apparent reason; unable to reproduce:

P Exiting due to unrecoverable panic: Could not start process "java\bin\javaw.exe" with working directory "C:\Users\IEUser\AppData\Local\Setlog\***\bundles": fork/exec java\bin\javaw.exe: The handle is invalid.

from pkg/system/api.go:113.

This sounds like a race condition within either Windows or GoLang's os/exec package.

Relicense to MIT

We have discussed internally a lot under which license we want to go OpenSource with.

GPLv3 forces people to return fixes back to us. But on the other hand, they would have to deliver a link to the sources - which is a PITA.

My suggestion is: MIT. It is copyleft and allows almost anything. The copyright notes have to stay with the source files if they are distributed… so we might thing about adding these to all of the source files.

We should decide this before our first v1.3.0 release!

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.