saltstack / salt-winrepo

Salt Windows Software Package Manager Repo

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Slack?

DavidJFelix opened this issue · comments

Ping @TheBigBear

So this is a weird one, I think and I may need some help.

So slack has a Windows installer. The installer operates silently when passed the -s flag.

Installation is pretty easy. However, I'm not sure how to denote version. Slack very clearly has a version. You can see it in the help and the uninstaller exists within a versioned path. However, the installer will grab the latest version. In fact, the installer is pretty atypical. Slack uses Squirrel. Squirrel autoupdates and uses nuget as a mechanism for library dependency downloading. It also installs to %LocalAppData%. It seems like each version of the app gets its own directory, named like app-1.2.0 within the slack folder of appdata (%LocalAppData%/slack/app-1.2.0). Within the app version folder there's an executable called Squirrel.exe that can be passed --uninstall to uninstall that version, but without knowing the version, it's not easy to know the full path to get to that. There is also an Update.exe within the top level slack directory which will uninstall all versions. Since slack seems to manage itself and auto update, I don't see any purpose in pretending we can control version. My proposal is the following slack.sls file:

slack:
  latest:
    full_name: Slack
    installer: 'https://slack.com/ssb/download-win'
    install_flags: '-s'
    uninstaller: '%LocalAppData%/slack/Update.exe'
    uninstall_flags: '--uninstall -s' 
    msiexec: False
    locale: en_US
    reboot: False

Thoughts?

@DavidJFelix there are already a few packages that use version 'latest'. This solution suggests itself if you got a single installer that doesn't change name with each version. (adobe flash is another one of them)
The githusetup.exe is planning to also switch to using Squirrel, btu right now uses MS Click-once and therefore can't be either installed or uninstalled in a /silent fashion. So there won't be a git-gui util such a time as they have an installer that can be used silently.

@DavidJFelix thanks for this one, well done.

@TheBigBear np. One question though, is the per-user %LocalAppData% okay? I wasn't sure if this would mesh well with system level packages.

Oh, I was assuming that you had tested this and it was working for you?
The %LocalAppData% is almost certainly a problem.
As it is a user variable and the user installing this will almost certainly differ between salt installing it and/or and admin.

Sorry, no. I'm still working on setting up and env for testing these. I'm in OSX/Linux most of the time. Hence the issue + the PR. Wanted to discuss this one a bit.

So how do we work on this? I know homebrew still works in OSX and it installs everything at user level.

@TheBigBear so what should we do about this?

@DavidJFelix I am a bit busy this week, sorry, ideally we should test it and see what actually happens. And there might be others that you submitted that may or may not work.

The winrepo downloader is not the smartest bit of software around, when dealing with detecting filenames.
Many URLs that it gets fed to it that doesn't end in the actual filename it might end up downloading some none sense random name, that then cant be executed.
Sorry, I will have to do better checks, will go back over things, but might take me a few days, a week at the most I think.
Sorry.

No problem about being busy, I totally understand. For the time being could we reopen this issue? I think this isn't closed, but also may be the place to discuss how to handle user-level installables.

@DavidJFelix yep, as feared, the winrepo downloader downloads a file called "download-win" which it then can't execute. So this pkg cannot be installed "as-is" at this point in time.

I am going to edit the 'sls' file and change the installer to point to 'salt://win/repo/slack' instead of the web URL. That way those desperate enough to install slack using salt winrepo can do so after they downloaded the installewr once and saved it on the salt master win repo.

Hope you agree and understand. There are two others alternatives that I see we are faced with:

  1. drop slack alltogether for now.
  2. fix the winrepo downloader so it detects the correct filename to download - just like the browsers do.

Good thing I'm a leet hacker who can use curl. curl -i https://slack.com/ssb/download-win reveals the headers on this page:

HTTP/1.1 302 Found
Content-Type: text/html
Date: Wed, 02 Sep 2015 14:37:51 GMT
location: https://slack-ssb-updates.global.ssl.fastly.net/releases/SlackSetup.exe
Server: Apache
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-Frame-Options: SAMEORIGIN
Connection: keep-alive

which contain a 302 redirect to slack's content delivery link: https://slack-ssb-updates.global.ssl.fastly.net/releases/SlackSetup.exe

Okay, so now that the link is taken care of... lets see if %LocalAppData% becomes an issue. If it is an issue, we should discuss how to handle this increasingly common case, where apps install per-user on windows systems.

Let's not close this issue yet.

So @TheBigBear. For my use case, I believe %LocalAppData% works. However, my use case is unusual and this may not work for typical use cases.

I'm currently running Salt-minion in a "local" mode, operating with no master. This requires a user to run salt-call from a privileged powershell window. What this means is that %LocalAppData% will evaluate to the logged in user which happens to be the same user that we're installing for. I believe that a user who installs salt-minion on Windows will be marked as the login user in the service that starts in the background.

  • For single user situations, this will be okay
  • For multi-user situations where each user installs salt-minion service, this will be okay (I assume this is rare)
  • For situations where some service account installs salt-minion service, this will not be okay.

Personally, I'm okay with this edge case, and not just because it "works for me", I'll explain why: We're merely hitting the bounds of a fundamentally flawed assumption. The assumption is that all packages are system-level. Salt does not have a means within pkg to install a package per user or per some variable filesystem. There is not "for user in x set, install package y". Homebrew has the exact same problem as a pkg back end.

Homebrew is a user-level package management system. The pkg brew backend simply checks which user the brew bin exists under and runs homebrew as that user -- it actively doesn't install per user. Another user on the system may or may not have access to the pkgs that the brew backend installs within salt.

So here's my suggested workflow within winrepo, assuming that this fundamentally flawed assumption is never fixed:

If you're a sysadmin that wants to have control over a system: install system level packages with a system level salt, running as a restricted service account. From that salt-master, install salt for every user and have those minions pull user-level packages. I'll note that this workaround currently has more functionality than the brew backend, since installing homebrew per user can cause serious issues.

We can continue discussing if you'd like, but I'm going to consider this issue closed unless you think my above suggestion is bad. Please let me know. :)

I'll note: in linux there's no good way aside from using salt.cmd.run to install a user-level binary to that user's ~/bin directory, which I see fairly regularly within a linux-heavy work environment.

@DavidJFelix good enough for me. The last bit about the way to do 'this sort' of thing in linux helped a lot. Thanks.

I'll consider attempting to add a module to salt that handles some of these per-user oddities, but it's pretty low priority with these minimally painful workarounds.

@DavidJFelix Sorry to chime in so late on this.

Regarding the salt-minion service: The salt-minion installation requires elevated privileges to install because the service runs under the local System account.

per user installations:
Are these MSI installations? or are they third party? We have code in the pkg.install that adds ALLUSERS=1 for msi's to force 'install for all users'. That may not be an option on an installer that doesn't use msiexec.

@twangboy so elevated privileges in windows really just means "run as administrator" which any user in the administrators group can do.

the pkg.installed only sets ALLUSERS=1 when the backend is msiexec (set by a winrepo arg) and allusers is set to true (set by a winrepo arg). neither of these are the case with this installer.

The big issue is that msiexec is the one that does the all users fan out... so winrepo can easy proxy pkg commands. With this package, pkg gives winrepo no mechanism to run this command "per user" so it has no choice but run for the log in user, which must be an admin, per the discussion above.

Hope this helps.

@DavidJFelix So, to clarify, what you're saying here is that you want to run a package installation as a specific user so that it will install for that user instead of doing an allusers installation using the Local System account the minion uses. Is that correct?

If so, we currently don't have a way to 'runas' a different user... It's a little tricky in windows when trying to shell out to a command line. We may have to take a different approach...

@twangboy uh. I wasn't aware of the local system account, as I'm not really a windows developer.

I have never and likely will never run salt in a minion/master fashion - I have no need for it. When I run salt in windows, I use salt-call, in an administrator-privledged powershell prompt.

I'm not sure what the solution is to running this in a minion/master fashion, but I certainly don't think the solution is offering fewer desirable packages because they can only be installed via salt-call directly.

Is it possible to set the salt-minion service to log on as the literal user to install software for by going into service, specifying properties > log on > this account within services?

@DavidJFelix Would you mind opening an issue in salt describing what you need here. As I understand it, you need to be able to install software for other users on the machine while running salt-call from and administrative command/powershell prompt. Basically you would want to execute the installer using the target user's credentials, correct? There may be some security issues there as it would require knowledge of the target user's password. There may be some other options we could explore to get this to work... I don't know how difficult this would be or how long it would take. It probably won't happen in the current release. Maybe the Boron release... depending on how they prioritize these.

@twangboy I think you're misunderstanding. Salt works perfectly fine for my purposes. salt-call works for me. The problem is that the slack package in winrepo won't work for people using salt with a master.

Again. I have to emphasize. Works for me.

@twangboy sorry, I responded to that at about midnight my time. For clarity, I'll explain exactly what I'm doing and what I'm looking to accomplish. I suppose this discussion should take place somewhere other than here, but since we're talking here, it should be fine. Sorry in advance for the novel, but this should clear up everything

I'm currently working on a system for local privileged users (local administrators on their own machines) to quickly bring a standard operating system image (either OS-standard or company-standard) to a level that they would consider usable for their job. This solution is primarily focused on developers and power users who have preferences/opinions about how their machine should work and what should be installed. With all that being said, what is important here is that I'm not using salt to propagate state change within remote systems. Our sysadmins do this already. They might even use salt (mine don't 👎 ). We're given an image as developers but it's still not our own. It's not ergonomic. So I use salt from this power-user's perspective, not from a local system user, but from a literal local person who has admin privileges on their machine. This system is closely modeled after the github/boxen project (puppet based) with some take-aways from opscode (chef based) efforts.

Quick aside: I recognize that salt does a lot more than this and may be like using a sledge hammer to tap in a finishing nail, so I'll walk you through my justification of using salt. Initially I had planned on using puppet. I know puppet from the linux world and I figured that existing boxen modules would help me accomplish my goal. What I ran into was a system that pretty much only works well in Linux. Puppet modules for homebrew were pretty bad and Windows support was almost nonexistent. Boxen had been created completely against all puppet standards and was so far from being loosely coupled that all their code was a complete throw-out for me. When looking into Windows support, I hit a major snag: chocolatey is utter garbage, while nuget is acceptable. Since puppet had no mechanism for easily installing windows msi's, what ended up happening was I was either forced to attempt an install on every run or write a module for puppet that did exactly what winrepo does. So this sent me on a search for a new solution. I looked into Chef, Ansible and Salt. Chef was still ruby, which I discovered is terrible in windows, and I didn't quite grok its syntax - nothing indicated good windows support. I regularly use Ansible and the syntax was simple and succinct, but there was no package manager abstraction and no real indications of how well it ran from a windows host. So when I looked into salt, I was almost given up on finding an existing system I could use. But I was met with a number of features that I immediately knew I needed.

  • Winrepo: I can't even begin to tell you how bad chocolatey is. Every other system seems to rely on it for windows support, but packages are downright wrong, chocolatey is slow and nobody seems to know how to write powershell. Their use of a literal repo instead of git makes changes have a huge cycle time. It's nothing like homebrew and it actively fights the fact that nobody packages for windows in a way that works with nuget, except library creators (which is what nuget handles).
  • gitfs: Chaining on chocolatey's use of a literal repo, the ability to use git as a filesystem backend for salt is a huge boon. Like homebrew and brew-cask, having git simply work makes getting configs down for salt super easy. Puppet had some minor attempts at this, but you had to bootstrap git yourself on windows, which became it's own issue. Puppet became prohibitively hard to use when working with multiple git sources, while salt still works great.
  • pkg abstraction: abstracting pkg even slightly for multiple platforms is really great. With winrepo for windows, brew for OSX and apt/yum/portage/pacman/etc for linux, this makes installing packages much easier and less verbose. The reason that boxen only works for OSX is fairly reasonable -- puppet makes multiple-platform configs a pain.
  • templated state files: At first this was hard for me to read, even having used jinja/mako/django templates in the past. But now that I've got it -- these are a huge boon to keeping state files succinct and free of bugs. Puppet files got exponentially more verbose as platforms were added. With salt, they only get linearly more verbose by adding a config in a map.jinja file.
  • formulas: a bit like modules in puppet or cookbooks in chef or playbooks in Ansible, but formulas are a little special. With gitfs as a delivery mechanism, they're not a pain to install. With template state files, they're not a pain to write. But most importantly, they don't have to be in their own repo or cycled into a module repository like Puppet -- they work fine in one flattened git repo in a homebrew-like setup. This makes a big deal in terms of visibility and succinct files.
  • masterless runs: Chef and Puppet actually do this basic part cleaner than salt. Salt wins because it can do it and it doesn't need anything like Puppet-librarian to bring in hundreds of modules from all over the web.

So back to my solution. I want something that people run as soon as they get a brand new computer so that it has everything they need exactly how they need it. Laptop died? OS corrupted? Everyone knows to back up data. People are using cloud storage like dropbox and google drive for that. But the machine config is a pain. The big one is: not like boxen. I don't want a "you know, for macs" tag line or to only support a few operating systems. I don't want to phone home to a puppet-master or salt-master or chef master. Almost nobody I'm targeting has that.

I want them to have an easy to use config that says "install this", "configure this a bit differently than normal" and have everything exactly how they left off. That's where we get to salt. I bring users in with a single command that bootstraps salt, fetches their system config and runs it to completion. Thats all users have to do. In the salt world, I bootstrap salt in a system-specific way, fetch a minion file, a top.sls file and eventually pillar data and run salt-call with a root set to local. You can see all of those here:

The top file is calling out salt formulas. At this time, I'm not using any formulas from the salt-formulas github group, though that will likely change. All of my formulas can be found called out in the minion file under https://github.com/hatchery/genepool.git These formulas are all still in development, but for the most part work for me today. I'm adding the ability to configure packages and trying to group them in a more coherent manner. The idea is that users should be able to find most things in my "genepool" repo, but if they can't, they can create their own formula and add it to their own minion file. They can also add other people's formulas as needed.

Right now, the bulk of my formulas target ubuntu, as that's my primary development platform. I've taken to destroying my AWS ubuntu image every other day to ensure that my system works for me. I've recently started taking on adding OSX and Windows functionality, which is why I'm here in winrepo making changes.

As you can see, allusers works great for me, but if I can't get allusers, having the user that runs it get the software is just as good (for me), because the user is the one taking the onus and installing their own software.

end novel

... but, having only the running user get the software means that salt-minion running as a service probably won't install it for a user, admin group or not. That gets us to a philosophical discussion -- is winrepo in the business of keeping packages that don't work 100%? I'd say there's already a precedence with Java (since it needs a local file that isn't included). I'm not sure how well winrepo works with multiple gitfs backends, but maybe this would be a good time to add another repo that contains all packages that don't work without some extra effort, and pull them out of the base winrepo.

@DavidJFelix Some great points and an interesting use case. Thanks for the detailed explanation.
@UtahDave, @TheBigBear (Please read the Novel) ^^^^