Create Shortcut on Users Desktops that Cannot Be Deleted

sapalmerBCS
New Contributor III

I'm failing in my attempt to create a .webloc file on all users desktop that the students cannot delete. I've create a DMG in composer with the .webloc file and the permissions set to 444. I deploy the DMG through Casper with FUT and FEU (either as a policy or with Casper Remote) and the file is placed correctly in the existing users Desktops and in the User Template folder. I check the permissions of the file on a non-Admin users desktop and it shows "-r--r--r--@ 1 john.doe wheel". I login as the non-Admin user and I am able to delete the file from my desktop.

What am I missing? I'm thinking it has to do with the extended attributes denoted by the @ at the end of the permissions, but I'm not exactly sure where to go from there.

1 ACCEPTED SOLUTION

mm2270
Legendary Contributor III

Have you tried setting the ownership of the webloc to root and also setting the system immutable flag on it? This is done like so, generally speaking:

sudo chown root /Users/user/Desktop/shortcut.webloc
sudo schg /Users/user/Desktop/shortcut.webloc

As long as the file is owned by root and the system immutable flag is set, since the users are not admins, they would not be able to move it to the trash, or delete it, or rename it, etc. Any operation that would alter it's location or name will pop up a dialog explaining that the file is locked. Move attempts will result in a copy into the new location, but the original will remain in place. If they do a Get Info on the file, it will show it's locked, but it will be grayed out so they can't uncheck it.
I should note that all the above is true even for local admins. Admins won't be able to delete it or move it to another location without first removing the system immutable flag. Only accounts with sudo privileges can do so, so you're standard users won't be able to do it, even if they looked up how to.

View solution in original post

10 REPLIES 10

mm2270
Legendary Contributor III

Have you tried setting the ownership of the webloc to root and also setting the system immutable flag on it? This is done like so, generally speaking:

sudo chown root /Users/user/Desktop/shortcut.webloc
sudo schg /Users/user/Desktop/shortcut.webloc

As long as the file is owned by root and the system immutable flag is set, since the users are not admins, they would not be able to move it to the trash, or delete it, or rename it, etc. Any operation that would alter it's location or name will pop up a dialog explaining that the file is locked. Move attempts will result in a copy into the new location, but the original will remain in place. If they do a Get Info on the file, it will show it's locked, but it will be grayed out so they can't uncheck it.
I should note that all the above is true even for local admins. Admins won't be able to delete it or move it to another location without first removing the system immutable flag. Only accounts with sudo privileges can do so, so you're standard users won't be able to do it, even if they looked up how to.

sapalmerBCS
New Contributor III

Thanks mm2270. That was almost exactly what I needed. Here are the steps I ended up taking that worked for anyone else that may try to do this.

Created a the shortcut (webloc file) on my desktop.
Opened terminal and ran

sudo chown root:wheel /Users/john.doe/Desktop/TestShortcut.webloc
sudo chmod 444 /Users/john.doe/Desktop/TestShortcut.webloc
sudo chflags uchg /Users/john.doe/Desktop/TestShortcut.webloc

I then recreated the DMG with Composer and pushed it out with FUT/FEU selected.

The file was created on all existing users desktops and the non-Admin users cannot delete the file.

mm2270
Legendary Contributor III

Oops! I notice I completely forgot to add the chflags portion of my command above. Glad you got it worked out despite my incomplete instructions!
However, just curious, but why did you go with uchg and not schg? If I'm not mistaken, with the former, it's still possible to delete the file if the ownership on it ever gets reset. With the latter, it can only b deleted once the flag is removed.
Not a big deal though, as long as it's working for you.

sapalmerBCS
New Contributor III

Honestly, I don't have a good reason for using uchg over schg. I had seen the former before and when I tried it after changing the owner of the file to root it worked. I noticed that unlike the unlocked file when I push out the locked file with FEU it leaves the owner as root:wheel so all is good.

Thanks again.

Eigger
Contributor III

Thank you for this post, its really helpful. I tried this process on a test computer and everything works as it should. When I deploy it to my users, they start getting "OSX Needs to Repair Your Library Error". What could possibly cause this? Thank you in advance.

seann
Contributor

You could also make a launchdaemon with a watchpatch of that desktop item. If it's removed, a script will be run to copy it back.

sapalmerBCS
New Contributor III

@Eigger I ended up having to roll back using the option to lock the file (last line in the script). It's been a few months, but I believe it was causing exactly what you are seeing. When it locked the file on the users desktop it ended up causing ownership issues on the entire user folder. I had to create a script and go remove the file from all the computers it had installed on (luckily for me that was just a couple carts). The shortcut is able to be deleted, unfortunately now, but I can run the policy as On-Going or Once Per Day if needed to make sure the link gets put back.

mm2270
Legendary Contributor III

Well, that's interesting that it doesn't work. I'm going to guess that it has something to do with adding a file that already has the uchg or schg flag set on the file added to a DMG package and having it installed via FEU/FUT. For those of you who have seen this, is it happening on any existing accounts only? Or on new accounts? Or both? Depending on which it is, it would be either the FEU or FUT part of the policy (or perhaps both) causing the problem.

What I'd suggest for those who still may want to do this is to instead use a package install with a postinstall script. Or maybe a DMG and FEU/FUT but with no special flags on the file and change the flag on it after it's copied into place. Here's an example script that may actually do the trick for those still interested in it. In this example, the .webloc is copied into /private/tmp/ and then copied into each home dir or if it's already there, the flag is checked and it's locked if needed.

#!/bin/bash

for USER in $(ls /Users | egrep -v "Shared"); do
    echo "Checking for webloc in /Users/$USER/"
    if [ -e "/Users/$USER/Desktop/Submit MAO Requests.webloc" ]; then
        if [[ $(ls -lO "/Users/$USER/Desktop/Submit MAO Requests.webloc" | grep " schg ") ]]; then
            echo "Webloc in /Users/$USER is already present and locked"
        else
            echo "Webloc is present in /Users/$USER but not locked. Fixing..."
            chflags schg "/Users/$USER/Desktop/Submit MAO Requests.webloc"
            echo "Webloc locked"
        fi
    else
        echo "Webloc not present. Copying and locking..."
        cp "/tmp/Submit MAO Requests.webloc" "/Users/$USER/Desktop/"
        chflags schg "/Users/$USER/Desktop/Submit MAO Requests.webloc"
        echo "webloc copied to /Users/$USER/Desktop/ and locked"
    fi
done

Eigger
Contributor III

Thanks @mm2270 what I did before is to just copy the webloc to Shared folder and use the cp command script to copy it to the current user, I was just gonna use the JSS ongoing policy and script to check if the webloc is existing on the user Desktop and if it was deleted by the user, the policy/script will just put it back the next time they log in. But using your script to lock it worked for us as it put less work on JSS by not constantly running the policy to look for the webloc and copying it back if not found.

StoneMagnet
Contributor III

@Eigger You can avoid burdening the JSS with an ongoing policy by doing as @seann suggested in their post - have a LaunchDaemon triggered by a WatchPaths key that restores the deleted file from a copy hidden on the user's machine.