Quantcast
Channel: Mac administration – Der Flounder
Viewing all 480 articles
Browse latest View live

Office 2016 DefaultsToLocalOpenSave setting change as of Office 2016 15.33.x

$
0
0

As part of the release of Office 2016 15.33.0, a number of managed preference options have been added and some have changed from what they were before. An example of one that has changed is the DefaultsToLocalOpenSave management setting, which sets the Open and Save options in Office 2016 apps to default to On My Mac instead of Online Locations.

In Microsoft Office 2016 15.32.x and earlier, the  DefaultsToLocalOpenSave setting could only be managed by running a command similar to the one below on the individual user accounts:

/usr/bin/defaults write "/path/to/user/homefolder/Library/Group Containers/UBF8T346G9.Office/"com.microsoft.officeprefs DefaultsToLocalOpenSave -bool true

To set this for all accounts on a particular Mac, I had written the following script:

As of Microsoft Office 2016 15.33.x, this setting can now be set at the global level for all users by running the following command with root privileges:

/usr/bin/defaults write /Library/Preferences/com.microsoft.office DefaultsToLocalOpenSave -bool true

I’ve posted an updated script for manage this setting to GitHub, available via the link below:

https://github.com/rtrouton/rtrouton_scripts/tree/master/rtrouton_scripts/set_office_2016_default_save_option_to_on_my_mac

This setting can now also be managed with a profile, so I’ve created a .mobileconfig file and posted it here on Github:

https://github.com/rtrouton/profiles/tree/master/Office2016DefaultToLocalSave



Using base64 encoding to include binary files inside scripts

$
0
0

When writing scripts, it’s sometimes useful to be able to be able to include and deploy binary files as part of the script run. An example of this would be if you want to use MySQL 5.6 and later’s option for creating a MySQL connection file. This is a file that allows you to store MySQL authentication inside an encrypted file named .mylogin.cnf.

Rather than trying to script the creation of a MySQL connection file, where the creation process would involve placing the MySQL authentication credentials in a readable format inside the script, it is easier and more secure to build the connection file manually on one machine and then encode the encrypted MySQL connection file into ASCII text using base64 encoding. Once encoded, the ASCII text can be decoded as part of a script designed to deploy the still-encrypted MySQL connection file to a desired location.

For more details on how to use base64 encoding, please see below the jump.

To encode files, you can use the openssl utility’s base64 function to encode them as ASCII characters. For example, a file named hello_world.txt with the following contents needs to be copied to the same location on multiple Macs:

--------

Hello, World!

---------

To encode the file, run the following command:

openssl base64 < /path/to/hello_world.txt

That will give you a ASCII string like that shown below:

LS0tLS0tLS0KCkhlbGxvLCBXb3JsZCEKCi0tLS0tLS0tLQo=

Screen Shot 2017 05 02 at 12 57 49 PM

You can then embed the string in a script and have it read back into a new file. For example, the script shown below will decode and store a copy of the hello_world.txt file inside the /Users/Shared directory:

#!/bin/bash

# Decode hello_world.txt stored in base64 format
# and store it as /Users/Shared/hello_world.txt.

openssl base64 -d <<HELLOWORLD > /Users/Shared/hello_world.txt
LS0tLS0tLS0KCkhlbGxvLCBXb3JsZCEKCi0tLS0tLS0tLQo=
HELLOWORLD

Running the script on the desired machines will allow the hello_world.txt file to be deployed into the desired location inside the /Users/Shared directory.

As files get larger, the block of ASCII text will also grow. Encoding the script shown above will produce a block of ASCII text that looks similar to this:

IyEvYmluL2Jhc2gKCiMgRGVjb2RlIGhlbGxvX3dvcmxkLnR4dCBzdG9yZWQgaW4g
YmFzZTY0IGZvcm1hdCAKIyBhbmQgc3RvcmUgaXQgYXMgL1VzZXJzL1NoYXJlZC9o
ZWxsb193b3JsZC50eHQuCgpvcGVuc3NsIGJhc2U2NCAtZCA8PEhFTExPV09STEQg
PiAvcGF0aC90by9oZWxsb193b3JsZC50eHQKTFMwdExTMHRMUzBLQ2tobGJHeHZM
Q0JYYjNKc1pDRUtDaTB0TFMwdExTMHRMUW89CkhFTExPV09STEQK

Screen Shot 2017 05 02 at 1 01 44 PM

This encoding technique can also be used to deploy entire executable binaries, where the program in question is encoded using the technique described above, then deployed to a desired location.


Looking up DUNS numbers for Apple’s VPP program

$
0
0

As part of an ongoing project, I needed to set up a new Apple VPP account for use with a test environment. The reason I did this was that I didn’t want to cause conflicts with our production VPP account. When I went to set up the account though, I ran into an interesting problem.

As part of the VPP account setup, I needed to provide a DUNS number. However, the DUNS number I had belongs to a company based outside of the US and Apple’s US VPP enrollment site would only accept DUNS numbers associated with US addresses. Instead, I needed to use the DUNS number for my company’s US subsidiary in place of the DUNS number that I had. The problem was that I had no idea what that DUNS number was.

After some research, I found a way to look up the DUNS number I needed and was able to successfully register my test environment’s VPP account with Apple. For more details, see below the jump.

Dun & Bradstreet, the company which runs the the DUNS system, provides a way to look up DUNS numbers on their website. To use this lookup, use the procedure shown below:

1. Go to http://www.dnb.com/duns-number/lookup.html

2. Go to Search By Company Name

Screen Shot 2017 05 17 at 3 09 52 PM

3. Enter your company information, check the I’m not a robot checkbox, then click the Search Now button.

Screen Shot 2017 05 17 at 3 09 53 PM

For example, here’s how to use this to find Walmart‘s DUNS number. I looked up the address of Walmart’s corporate headquarters in Benton, Arkansas and did a search using that.

Screen Shot 2017 05 17 at 3 13 06 PM

The site gave me several options to choose from and I picked the most likely one, based on the address and phone number information I had for Walmart.

Screen Shot 2017 05 17 at 3 13 26 PM

I was requested to enter an email address, to have the DUNS information emailed to me.

Screen Shot 2017 05 17 at 3 14 14 PM

Shortly afterwards, I received an email with the appropriate DUNS number.

Screen Shot 2017 05 17 at 4 06 52 PM


Application blacklisting using management profiles

$
0
0

When deploying Macs for use in classrooms or for training, there is occasionally a requirement that certain applications must be blocked from running. Usually, this is to make sure that the student or test taker using the Mac is not able to use the blocked applications because it would distract them or otherwise cause problems.

On iOS, there is a way to do this via the blacklistedAppBundleIDs key available in the Restrictions payload. However, this key is not available on macOS and Macs will ignore the blacklist.

On macOS, there is the ability to set an application whitelist via Profile Manager but not a blacklist.

Screen Shot 2017 05 20 at 2 45 31 PM

However, the profile specification does include the ability to configure an application blacklist using the pathBlackList key in the settings managed by the com.apple.applicationaccess.new payload.

Screen Shot 2017 05 20 at 2 28 46 PM

For more details, see below the jump.

Since the ability to set an application blacklist for macOS is currently missing from Profile Manager, a profile to blacklist application may need to be manually created. See below for an example profile which blacklists the following applications:

/Applications/Chess.app
/Applications/FaceTime.app
/Applications/Mail.app
/Applications/Messages.app

Screen Shot 2017 05 20 at 3 11 56 PM

Note: In addition to setting the application blacklist, a correctly-built profile will need to include whitelist entries that explicitly allow all other applications other than the ones being blacklisted.

Screen Shot 2017 05 20 at 3 14 26 PM

When setting an application blacklist using the profile, one thing to be aware of is that the blacklist can be overridden by an administrator account.

Screen Shot 2017 05 20 at 3 19 00 PM

If an administrator chooses, they can set the application block to be overridden once or permanently.

Screen Shot 2017 05 20 at 3 22 32 PM

Screen Shot 2017 05 20 at 3 23 23 PM

For those who want to block applications using a management profile, I’ve created an example .mobileconfig file and posted it here on Github:

https://github.com/rtrouton/profiles/tree/master/BlacklistApplications


Creating Jamf Pro QuickAdd installer packages which do not install the Jamf Pro management user account

$
0
0

Jamf Pro-managed Macs usually have a management account on the Mac, which is normally created as part of the Mac’s enrollment in the Jamf Pro service. This may cause issues in some Mac environments, where the creation of local user accounts is tightly controlled to help minimize opportunities for malicious third parties to compromise unused accounts.

To help protect against the Jamf Pro management account being compromised, Jamf has added some protections. These protections include including the ability to set a random password for the account on a per-machine basis and the ability to rotate the password on a regular basis.

Screen Shot 2017 05 26 at 9 06 02 PM

Depending on your needs though, it is also possible avoid setting up the Jamf Pro management account on Macs. The reason for this is that the Jamf Pro agent by and large does not need the Jamf Pro management account in order to work properly.

As of Jamf Pro 9.99.0, the Jamf Pro management account is used for the following:

If you are not using Jamf’s Remote application for remote screen sharing, or enabling the Jamf Pro management account for FileVault 2, it is not necessary to install the Jamf Pro management account on Jamf Pro-managed Macs at all. For more details, see below the jump.

The usual method of enrolling a Mac into Jamf Pro uses a QuickAdd installer package, generated by Jamf’s Recon application or via user-initiated enrollment.

Here’s how you can configure Recon to generate a QuickAdd package that does not install the Jamf Pro management account:

1. Launch Recon
2. Select QuickAdd Package
3. Specify the name of the management account you want to use

Screen Shot 2017 05 26 at 8 43 29 PM

4. In the Method for Setting Password: drop-down menu, select Randomly generate password.

This will cause two things to happen in the Recon interface.

A. The Create management account if it does not exist option will be enabled

Screen Shot 2017 05 26 at 8 43 54 PM

B. The Create… button in the lower-right corner will go from grayed-out to active.

Screen Shot 2017 05 26 at 8 43 55 PM

5. Uncheck the Create management account if it does not exist option

This will cause the In the Method for Setting Password: drop-down menu to display Specify password… , but the Create… button in the lower-right corner will remain active.

Screen Shot 2017 05 26 at 8 44 08 PM

6. Set any other desired options.

7. Click the Create… button

Screen Shot 2017 05 26 at 8 45 46 PM

The Recon application will generate a QuickAdd package that will enroll the Mac in the appropriate Jamf Pro server, but the newly-created QuickAdd will not create the Jamf Pro management account on the Mac as part of the installation process.

Screen Shot 2017 05 26 at 9 41 59 PM

Screen Shot 2017 05 26 at 9 28 18 PM

Screen Shot 2017 05 26 at 9 28 43 PM

Note: The computer will still appear in the Jamf Pro server’s inventory as a managed computer with the management account listed.

Screen Shot 2017 05 26 at 9 30 04 PM

The same method can used with user-initiated enrollment. To set the QuickAdd packages generated by the user-initiated enrollment process to not create the management user account, use the following procedure:

1. Log into your Jamf Pro server.
2. Go to Management Settings: Global Management and select User-Initiated Enrollment

Screen Shot 2017 05 26 at 8 51 53 PM

3. Under Platforms: macOS, uncheck the Create management account setting.

Screen Shot 2017 05 26 at 8 51 20 PM

Note: There is no need to change the Method for Setting Password or Password Length settings.


AutoPkg recipes for Apple Enterprise Connect

$
0
0

To help keep on top of software updates, I’ve been using AutoPkg in combination with AutoPkgr and JSSImporter for a while now to upload new software updates to Jamf Pro. However, I recently ran into a challenge when I wanted to build an AutoPkg recipe for Apple’s Enterprise Connect.

AutoPkg recipes usually rely on the vendor having a publicly accessible way to get downloads via HTTP or HTTPS. Apple does not have a publicly accessible download URL for Enterprise Connect and in fact discourages customers from sharing the download link. The fact that there was a download link meant that I could write AutoPkg recipes but at the same time I couldn’t include the URL needed to download the latest update as part of the recipe .

After some thinking and research into AutoPkg’s functionality, I found a way to create AutoPkg recipes for Enterprise Connect while at the same time not sharing Apple’s download URL. For more details, see below the jump.

The solution is to use an AutoPkg recipe override to store the download URL for Enterprise Connect. Recipe overrides are locally-stored files that allow you to change certain input variables in AutoPkg recipes.

Since the recipe overrides are stored locally on the Mac which is running AutoPkg and not shared with any other resources, Apple’s download URL for Enterprise Connect is only made available to the AutoPkg installation running on that specific Mac.

I have written AutoPkg recipes for Enterprise Connect, which are available from here:

https://github.com/autopkg/rtrouton-recipes/tree/master/EnterpriseConnect

By default, the EnterpriseConnect.download recipe contains a non-functional placeholder value and requires that placeholder value to be overridden before the recipe will work.

Screen Shot 2017 06 12 at 4 36 11 PM

To use the Enterprise Connect recipes, you will need to create a recipe override of the desired recipe and enter the URL Apple sends you into the DOWNLOAD_URL value of the override. Here’s an example of using, using AutoPkgr and the EnterpriseConnect.jss recipe.

1. Launch AutoPkgr.

Screen Shot 2017 06 12 at 2 10 35 PM

2. If needed, add the rtrouton-recipes repo to AutoPkg.

3. Click on the Repos & Recipes tab and locate the EnterpriseConnect.jss recipe

4. Right-click on the EnterpriseConnect.jss recipe and select Create Override…

Screen Shot 2017 06 12 at 9 53 05 AM

 

5. Give the recipe override a unique name.

Screen Shot 2017 06 12 at 9 53 37 AM

6. Go to /Users/username_goes_here/Library/AutoPkg/RecipeOverrides and locate the newly-created recipe override file.

Screen Shot 2017 06 12 at 9 55 40 AM

7. Open the recipe override file file in a text editor and locate the DOWNLOAD_URL value.

Screen Shot 2017 06 12 at 9 58 55 AM

8. Change the DOWNLOAD_URL value of the override from the non-functional placeholder value to whatever the current download URL is for Enterprise Connect.

Screen Shot 2017 06 12 at 9 58 09 AM

When you run the recipe override using AutoPkg, it should use the Enterprise Connect’s current download URL in place of trying to use the non-functional placeholder value.

Note: The download.apple.com URL shown in the example above is also a placeholder. As I mentioned earlier, Apple discourages customers from sharing the download link.

Apple’s download URL for Enterprise Connect may change, so you will need to check and update the download URL as needed in the recipe override when you’re notified by Apple that a new Enterprise Connect version is now available.


Activating EndNote X8 using management profiles

$
0
0

I’ve moved on from a role where I needed to support Clarivate Analytics’s EndNote bibliography software, but I noticed that my colleague Rusty Myers is now deploying it in his environment.

As part of his work, Rusty discovered that it was possible to bypass the activation process by adding the AcceptedENX7.2EULA key to /Library/Preferences/com.ThomsonResearchSoft.EndNote.plist:

In Rusty’s case, the key is being added by running the following commands with root privileges:

/usr/bin/defaults write "/Library/Preferences/com.ThomsonResearchSoft.EndNote.plist" "AcceptedENX7.2EULA" -string "1"

Reading through Rusty’s post, I wondered if you could apply this setting via a management profile instead of writing the necessary values to /Library/Preferences/com.ThomsonResearchSoft.EndNote.plist. With some testing, I verified that it’s possible to also bypass the activation process with a management profile.

For those who want to bypass EndNoteX8’s activation process using a management profile, I’ve created a .mobileconfig file and posted it here on Github:

https://github.com/rtrouton/profiles/tree/master/ActivateEndNote/EndNoteX8

I’ve also created one for EndNoteX7, since it appears that the setting has not changed since EndNoteX7’s release. However, I do not have access to that version of EndNote and can’t test it to make sure.

If you’re still deploying EndNote X7, please give it a try and let me know. The .mobileconfig file for EndNoteX7 has been posted here on Github:

https://github.com/rtrouton/profiles/tree/master/ActivateEndNote/EndNoteX7


Enabling least-privilege screensharing using Apple’s Remote Desktop Client and Screen Sharing.app

$
0
0

In a number of Mac-using environments, there is often a need for IT staff to remotely connect to a Mac’s screen using Apple’s Remote Desktop application and work with the person on the other end to resolve a problem. However, there can be several technical and human-centric issues with enabling remote assistance:

  1. Authentication – To enable access using a username and password, that user account must be granted access rights by belonging to a group or by explicitly granting rights to a local account.
  2. Password rotation – If you’re enabling screensharing via granting access to a local account, the security requirements in most environments mandate that those passwords be changed on a regular basis. However, securely changing the account password on multiple remote Macs can be a management challenge on its own.
  3. Access privileges – A lot of folks don’t like the idea that someone they don’t know can take over access to their keyboards and screens without the remote customer saying it’s OK for them to do so. Frankly, I’ve been on both sides of this fence and I don’t like it either.

However, there is a way to enable screen sharing using Apple’s Remote Desktop Client and Apple’s Screen Sharing.app which does the following:

  • Removes the need for any account to be enabled for screen sharing access
  • Mandates that all screen sharing access be approved by the logged-in user
  • Does not allow screen sharing access if no user is logged in.

For more details, see below the jump.

To configure Apple’s Remote Desktop Client to allow only explicitly-permitted screen sharing access, use the following procedure:

1. Log into the Mac in question
2. Open System Preferences
3. Select the Sharing preferences

Screen Shot 2017 07 07 at 1 52 31 PM

4. Check the Remote Management box to turn on the Remote Desktop Client

Screen Shot 2017 07 07 at 1 54 55 PM

5. In the Allow access for: section, select the Only these users: option, but do not select any users.

Screen Shot 2017 07 07 at 1 17 39 PM

6. Click the Computer Settings… button.

Screen Shot 2017 07 07 at 2 31 56 PM

7. Select the Anyone may request permission to control screen option, then click the OK button.

Screen Shot 2017 07 07 at 1 17 25 PM

8. Close System Preferences

You may also configure the Remote Desktop Client using Apple’s kickstart utility. To set the above configuration using the kickstart utility, run the command shown below with root privileges:

/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -allowAccessFor -specifiedUsers -setreqperm -reqperm yes

Screen Shot 2017 07 07 at 1 19 40 PM

Once the Remote Desktop Client is configured this way, the Remote Desktop Client should not allow any remote user to authenticate successfully, but will allow the logged-in user to permit screen sharing requests from remote users.

To screen share with a remote Mac configured this way, use the following procedures:

Sending a screen sharing request

1. Open the Screen Sharing application
2. Under the Connection menu, select New…

Screen Shot 2017 07 07 at 2 05 56 PM

3. In the Connect To: blank, enter the DNS name or IP address of the remote Mac then click the Connect button.

Screen Shot 2017 07 07 at 1 25 42 PM

4. When prompted to log in, select By requesting permission.

Screen Shot 2017 07 07 at 1 50 25 PM

5. Once By requesting permission is selected, click the Connect button.

Screen Shot 2017 07 07 at 1 25 48 PM

6. Wait for the response.

Screen Shot 2017 07 07 at 1 25 52 PM

Accepting a screen sharing request

1. On the remote Mac’s screen, a Share Screen Request prompt will appear to the logged-in user.

Screen Shot 2017 07 07 at 2 36 50 PM

2. If all appears OK, click the Share Screen button.

Screen Shot 2017 07 07 at 1 26 01 PM

Once the request has been accepted, the remote Mac’s screen should appear in the Screen Sharing application.

Screen Shot 2017 07 07 at 2 24 31 PM

With this Remote Desktop Client configuration, there must be a logged-in user in order for a screen sharing connection to take place. If no user is logged in, then the By requesting permission option will not appear in the login prompt.

Screen Shot 2017 07 07 at 1 49 56 PM

This method only enables the following functions: 

  1. Screen sharing
  2. The ability to copy files from the remote Mac, by dragging and dropping the file from its location on the remote Mac to a location outside of the Screen Sharing window.

None of the Remote Desktop Client’s other features will be enabled, including the ability to copy files to the remote Mac, pull reports from the remote Mac, or the ability to run commands on the remote Mac. 



Generating printer configurations using payload-free_package_printer_generator.sh

$
0
0

As part of a recent discussion, a colleague posted in the MacAdmins Slack that they needed to deploy printers as part of a DeployStudio workflow. DeployStudio doesn’t natively include this functionality, so that meant developing a way to deploy the desired printers to the appropriate Macs via one of the following methods:

As part of the conversation, I pointed to Nick McSpadden‘s PrinterGenerator tool:

https://github.com/nmcspadden/PrinterGenerator

Nick’s tool is designed to create printer configurations for deployment via Munki. However, my colleague wasn’t using Munki in this case and didn’t plan to deploy it. So even though there was a tool that could have solved the problem, adapting it to work for my DeployStudio-using colleague’s needs was going to take some time and effort.

The discussion got me started thinking about the problem of printer deployments and ways to solve it that could work for the vast majority of deployment solutions. After some research and testing, I’ve developed a solution that may work for most deployment needs. For more details, see below the jump.

My solution was to build a script named payload-free_package_printer_generator.sh, which does three tasks:

  1. Accept printer configuration input.
  2. Use that input to generate a script which uses the lpadmin tool to create printers with the provided configuration information.
  3. Generate a payload-free package to run the script.

Running the script

Usage

/path/to/payload-free_package_printer_generator.sh -n -l -d -a -p -1 -2 -3 -4 -5 -6 -7 -8 -9 -c

Options:

  • -n: Name of the print queue. May not contain spaces, tabs, # or / characters. (required)
  • -l: The physical location of the printer. Examples may include Reception Desk, Librarian’s Office or Second Floor, Room 2C456 (optional)
  • -d: The printer name which is displayed in the Printers & Scanners pane of System Preferences, as well as in the print dialogue boxes. (required)
  • -a: The IP or DNS address of the printer. Protocol must be specified as part of the address (for example, use lpd://ip.address.goes.here or lpd://dns.address.goes.here for LPR printing.) (required)
  • -p: Name of the driver file in /Library/Printers/PPDs/Contents/Resources/. This must use the full path to the drive (starting with /Library). (required)
  • -1: Specify first printer option. (optional)
  • -2: Specify second printer option. (optional)
  • -3: Specify third printer option. (optional)
  • -4: Specify fourth printer option. (optional)
  • -5: Specify fifth printer option. (optional)
  • -6: Specify sixth printer option. (optional)
  • -7: Specify seventh printer option. (optional)
  • -8: Specify eighth printer option. (optional)
  • -9: Specify ninth printer option. (optional)
  • -c: Name of the Apple Developer ID Installer certificate being used to sign the payload-free package. Certificate name should be formatted like Developer ID Installer: Your Name or Developer ID Installer: Your Name (F487797D). (optional)

Note: This script needs to be run with root privileges.

Examples

To create an unsigned payload-free package using only the required printer configuration options, run the command shown below with root privileges:

/path/to/payload-free_package_printer_generator.sh -n PrinterQueueGoesHere -d PrinterNameGoesHere -a lpd://ip.address.goes.here -p /Library/Printers/PPDs/Contents/Resources/PrinterDriverPPDHere.gz

Screen Shot 2017 07 18 at 3 32 45 PM

The script’s output should appear similar to that shown below:

The script will generate a postinstall script that looks like this:

Once the postinstall script has been created, a payload-free package will be generated using the script. Once the package has been generated, a new Finder window will appear to show the completed package’s location.

Screen Shot 2017 07 18 at 3 40 46 PM

If you need to sign the payload-free package, that is possible using the -c option. For example, you may need to create a signed package that sets up a printer with the following settings:

Printer Queue Name:  ReceptionDeskBrotherLaserPrinter
Printer Location:  Reception Desk
Printer Display Name:  Reception Desk Brother Laser Printer
Printer Address:  lpd://192.168.1.186
Printer Driver:  /Library/Printers/PPDs/Contents/Resources/Brother HL-2170W series CUPS.gz

To create an signed payload-free package which can create this printer, run the command shown below with root privileges:

/path/to/payload-free_package_printer_generator.sh -n ReceptionDeskBrotherLaserPrinter -l "Reception Desk" -d "Reception Desk Brother Laser Printer" -a lpd://192.168.1.186 -p "/Library/Printers/PPDs/Contents/Resources/Brother HL-2170W series CUPS.gz" -c "Developer ID Installer: Rich Trouton (XF95CST45F)"

Screen Shot 2017 07 18 at 3 25 00 PM

You may be prompted to authorize access to your Developer ID certificate.

Screen Shot 2017 07 18 at 3 24 30 PM

Once authorized, the package will be generated.

Screen Shot 2017 07 18 at 3 25 43 PM

You can verify that the package is signed by clicking on the padlock icon in the Installer window.

Screen Shot 2017 07 18 at 3 25 48 PM

Screen Shot 2017 07 18 at 3 25 52 PM

Testing

To test a payload-free package generated by this script, take it to a Mac which does not already have the desired printer set up on it and run the installer package.

Note: The appropriate printer drivers must be installed prior to setting up the printer. If not, the lpadmin tool which is used by the payload-free package to set up the printer will generate an error and the installer package will report a failed install.

Screen Shot 2017 07 18 at 3 26 01 PM

Screen Shot 2017 07 18 at 3 26 24 PM

Screen Shot 2017 07 18 at 3 26 26 PM

The printer should be set up as specified.

Screen Shot 2017 07 18 at 3 26 44 PM

Screen Shot 2017 07 18 at 3 26 55 PM

Screen Shot 2017 07 18 at 3 26 58 PM

The script is available below. It is also available from GitHub at the following address:

https://github.com/rtrouton/payload-free_package_printer_generator


Deploying a pre-configured F5 Big-IP VPN client

$
0
0

As part of a discussion with a colleague, he said that he needed to build an installer for his shop’s F5 Network’s VPN service but wasn’t sure how. I hadn’t built one of these previously either, so I decided to look into it.

Fortunately, F5 Networks has made the process of creating one a fairly straightforward process, assuming that your VPN administrator can provide the needed config_tmp.f5c configuration file. Assuming that you can get that file, all that’s needed is making sure that the config_tmp.f5c file is located in the same directory as the VPN client installer.

Screen Shot 2017 07 26 at 8 27 48 PM

The reason for this is that the postinstall scripts of the F5 VPN client installer are set to look for that file in that location, and will automatically import the configuration file’s contents if the file is found.

Screen Shot 2017 07 26 at 8 16 13 PM

Once I had both the config_tmp.f5c config file and a copy of the F5 VPN client installer, I was able to create an installer using this method that handled both the installation and the automated configuration of the F5 VPN client. For more details, see below the jump.

Prerequisites:

  • Packages
  • The F5 VPN client installer (provided by your VPN administrator)
  • The appropriate config_tmp.f5c config file (provided by your VPN administrator)

1. Set up a new Packages project and select Raw Package.

Screen Shot 2017 07 26 at 7 52 12 PM

2. In this case, I’m naming the project F5 BIG-IP VPN Client

Screen Shot 2017 07 26 at 7 52 49 PM

 

3. Once the Packages project opens, click on the Project tab. You’ll want to make sure that the your information is correctly set here (if you don’t know what to put in, check the Help menu for the Packages User Guide. The information you need is in Chapter 4 – Configuring a project.)

Screen Shot 2017 07 26 at 7 53 24 PM

In this example, I’m not changing any of the options from what is set by default.

4. Next, click on the Settings tab. In the case of my project, I want to install with root privileges and not require a logout, restart or shutdown.

To accomplish this, I’m choosing the following options in the Settings section:

  • In the Post-Installation Behavior section, set On Success: to Do Nothing
  • In the Options section, check the box for Require admin password for installation.
Screen Shot 2017 07 26 at 7 53 31 PM

 

5. Click on the Scripts tab in your Packages project.

Screen Shot 2017 07 26 at 7 53 37 PM

6. Select the F5 VPN client installer and drag it into the Additional Resources section of your Packages project.

Screen Shot 2017 07 26 at 8 05 14 PM

7. Select the config_tmp.f5c config file and drag it into the Additional Resources section of your Packages project.

Screen Shot 2017 07 26 at 8 05 25 PM

8. The last piece is telling the F5 VPN installer to run. For this, you’ll need a postinstall script. Here’s the one I’m using:

9. Once you’ve got the postinstall script built, run the following command to make the script executable:

sudo chmod a+x /path/to/postinstall

10. Once completed, add the postinstall script to your Packages project.

Screen Shot 2017 07 26 at 8 05 56 PM

11. Last step, go ahead and build the package. (If you don’t know to build, check the Help menu for the Packages User Guide. The information you need is in Chapter 3 – Creating a raw package project and Chapter 10 – Building a project.)

 

Testing the installer

Once the package has been built, test it by taking it to a test machine that does not have the F5 VPN client and install it. The end result should be that the F5 VPN client installs along with the specified VPN configuration.


Setting a macOS VM to automatically boot to Recovery HD using VMware Fusion

$
0
0

When testing various security functions, like System Integrity Protection or High Sierra’s new kernel extension functionality, it’s often useful to be able to boot a macOS virtual machine (VM) into the Recovery environment. However, it can be challenging to select the VM and hold down Command+R in time to boot to the Recovery environment. This can result in having to try several or more times before you can successfully boot the VM to Recovery HD.

Fortunately, VMware has a setting that enables a forced boot to Recovery HD. For more details, please see below the jump.

My colleague mosen discovered that you could add the following setting to a macOS VM’s .vmx configuration file:

macosguest.forceRecoveryModeInstall = "TRUE"

Once this setting has been added to the .vmx configuration file, the VM will automatically boot to Recovery HD the next time it is started.

To add the macosguest.forceRecoveryModeInstall setting to a macOS VM:

1. Shut down the relevant VM.
2. Open the VM’s .vmx file for editing.

Screen Shot 2017 07 31 at 10 26 39 PM

3. Add the following line to the end of the .vmx configuration file:

macosguest.forceRecoveryModeInstall = "TRUE"

Screen Shot 2017 07 31 at 10 29 57 PM

4. Save the changes to the .vmx configuration file.
5. Start the VM.

The VM should boot from the macOS VM’s Recovery HD partition automatically, and will continue to boot to Recovery until the setting is removed from the VM’s .vmx file.

Screen Shot 2017 07 31 at 10 52 18 PM


Kernel extensions and macOS High Sierra

$
0
0

As part of the pre-release announcements about macOS High Sierra, Apple released the following KBase article:

As part of the KBase article, Apple included a Changes coming with macOS High Sierra section which featured this note:

macOS High Sierra introduces a new feature that requires user approval before loading new third-party kernel extensions. This feature will require changes to some apps and installers in order to preserve the desired user experience.

Screen Shot 2017 08 23 at 9 33 49 PM

That section in turn links to this KBase article, which describes the behavior in more detail:

To improve security on the Mac, kernel extensions installed with or after the installation of macOS High Sierra require user consent in order to load. This is known as User Approved Kernel Extension Loading. Any user can approve a kernel extension, even if they don’t have administrator privileges.


Screen Shot 2017 08 23 at 10 23 34 PM

What’s all this mean? For more details, see below the jump.

Apple has been trying to discourage third party software developers from using kernel extensions for the past few years. The reason for this has been that kernel extensions are able to plug into the macOS kernel’s space and access low-level resources, like hardware devices. The issue for Apple is that, when kernel extensions aren’t working right, the whole OS has problems that wouldn’t otherwise happen.

As an example of this, if an application which doesn’t use a kernel extension has a memory error, the worst consequence is that the affected application crashes. The rest of the OS is fine though, thanks to the OS’s memory protections. However, if a kernel extension has a similar issue, the kernel doesn’t have similar memory protections. A memory error in a kernel extension can cause a kernel panic, which crashes the whole operating system.

As a result, starting with OS X Mavericks, Apple has been making changes to how third party kernel extensions have been allowed to operate:

OS X Mavericks

Kernel extensions should be digitally signed using an Apple Developer ID for Signing Kexts certificate, but this code signing requirement is not enforced strictly. Unsigned kernel extensions can still be installed into /System/Library/Extensions, which is where kernel extensions have been installed up until OS X Mavericks. However, signed kernel extensions must be installed into /Library/Extensions.

OS X Yosemite

Kernel extensions must be digitally signed using an Apple Developer ID for Signing Kexts certificate and installed into /Library/Extensions. However, it is still possible on OS X Yosemite to enable a kernel extension developer mode which disables the code signing requirement.

OS X El Capitan

Kernel extensions must be digitally signed using an Apple Developer ID for Signing Kexts certificate and installed into /Library/ExtensionsSystem Integrity Protection, introduced as part of OS X El Capitan, now enforces code signing and explicitly disables the kernel extension developer mode previously available in OS X Yosemite.

macOS Sierra

Kernel extensions must be digitally signed using an Apple Developer ID for Signing Kexts certificate and installed into /Library/Extensions. System Integrity Protection remains the enforcement mechanism.

macOS High Sierra

Kernel extensions must be digitally signed using an Apple Developer ID for Signing Kexts certificate and installed into /Library/Extensions. System Integrity Protection remains the enforcement mechanism. Kernel extensions will not load unless authorized to do so by a logged-in user.

Note: This authorized user does not need to have admin rights, so any logged-in user can authorize the loading of a kernel extension.

What are the likely consequences of this change in High Sierra?

  • For the individual consumer owner of a Mac, this will likely not be a big deal. Since anybody can authorize the loading of the kernel extension, the individual can go click whatever is needed and continue on with their day. Potentially not a great user experience, but not awful.
  • For Mac admins, this change is potentially going to be a huge pain in the neck. A number of third-party applications used in education and enterprise environments use kernel extensions, especially antivirus and other security-focused solutions. Now these kernel extensions are not going to load automatically and it’s going to be up to the individual users who use those machines as to whether or not those kernel extensions get loaded.

That said, Apple has stated that third-party kernel extensions won’t require authorization under the following conditions:

  • The third party kernel extension(s) in question were on the Mac before the upgrade to macOS High Sierra.
  • The third party kernel extension(s) in question are replacing previously approved extensions.

Apple has also provided a couple of ways that companies, schools or institutions can deal with this issue:

1. Boot into macOS Recovery and use the spctl command line tool.

Note: Apple has not yet specified how this tool should be used in High Sierra’s Recovery environment. The guidance provided is Run the command by itself to get more information about how to use the spctl command

Screen Shot 2017 08 23 at 10 31 55 PM

Another section of this KBase article also notes that resetting NVRAM will revert the Mac in question back to requiring user authorization to load kernel extensions.

Screen Shot 2017 08 23 at 10 53 33 PM

2. Enroll your Macs with a mobile device management (MDM) solution. If a Mac is enrolled with an MDM solution, even if that MDM solution isn’t being used to actively manage the Mac in question, the new kernel extension authorization behavior is disabled and kernel extension behavior goes back to that enforced by macOS Sierra:

Kernel extensions must be digitally signed using an Apple Developer ID for Signing Kexts certificate and installed into /Library/Extensions. System Integrity Protection remains the enforcement mechanism.

Conclusion

Apple is advertising these changes now so that Mac admins can have at least some chance to prepare their environments before macOS High Sierra is released in the fall. For those shops which are already using a mobile device management solution with their Macs, the new kernel extension behavior should be a non-event on High Sierra’s release day. High Sierra should detect that the Mac is enrolled in MDM and revert to macOS Sierra’s behavior of automatically allowing properly signed kernel extensions to load.

For those shops which aren’t currently using a mobile device management solution with their Macs, they currently appear to have the following choices for macOS High Sierra:

  1. Allow their user population to handle the new kernel extension authorization process
  2. Use the new macOS Recovery-based process of using the spctl tool in the Recovery environment to disable the new kernel extension behavior
  3. Get a mobile device management solution and enroll their Macs running macOS High Sierra.

Adding password protection to manually installed management profiles

$
0
0

While working with some colleagues, I recently built a management profile that my one colleague requested to be set as non-removable. Normally, this can be accomplished by setting the PayloadRemovalDisallowed key in the profile to a boolean value of true.

Screen Shot 2017 08 24 at 3 32 10 PM

I provided the profile to my colleague and he tested it out. However, in the course of testing, he discovered that the profile could be removed by a user with administrative rights using the following procedure:

1. Open System Preferences
2. Select the profile in question.
3. Click the minus button.

Screen Shot 2017 08 24 at 3 26 17 PM

4. Be warned about removing a locked profile.

Screen Shot 2017 08 24 at 3 29 52 PM

5. Enter admin credentials when prompted.

Screen Shot 2017 08 24 at 3 27 17 PM

After entering admin credentials, the profile was then removed.

When I checked Apple’s reference documentation on configuration profiles, the issue came down to how the profile was being delivered. Apple’s documentation includes the following note about the PayloadRemovalDisallowed key:

Screen Shot 2017 08 24 at 2 44 26 PM

This profile was being installed by an installer package, so from Apple’s point of view, it was being installed manually. That meant that the manual installation behavior, where the profile could be removed by anyone with admin rights, was the applicable behavior here.

Another colleague working with us on this issue suggested adding a removal password to the profile, using Apple’s com.apple.profileRemovalPassword profile payload.

Screen Shot 2017 08 24 at 3 01 15 PM

A removal password for a profile is designed to allow the removal of a management profile, even if that profile is otherwise set to be non-removable. For more details, see below the jump:

In our case, we were seeking to block removal rather than facilitate it. However, having the removal password added as a payload worked for our purposes as well because now the profile could not be removed without supplying the password. An example Removal Password payload is available below:

Once the Removal Password payload is added to a profile where PayloadRemovalDisallowed set to true, the removal process for a manually installed profile now looks like this:

1. Open System Preferences
2. Select the profile in question.
3. Click the minus button.

Screen Shot 2017 08 24 at 3 26 17 PM

4. Be warned about removing a locked profile and that removal will require a password.

Screen Shot 2017 08 24 at 3 26 38 PM

5. Supply the removal password when prompted.

Screen Shot 2017 08 24 at 3 27 01 PM

6. Enter admin credentials when prompted.

Screen Shot 2017 08 24 at 3 27 17 PM

If the profiles command line tool is being used to remove the profile in question, the -z option can be used to supply a profile removal password.

Screen Shot 2017 08 24 at 3 48 01 PM

To show the Removal Password payload in the context of a full management profile, please see below:

Screen Shot 2017 08 24 at 3 32 25 PM


Building a Jamf Pro smart group containing High Sierra-incompatible Mac models

$
0
0

As part of preparing for macOS Sierra in 2016, I prepared a smart group that listed Macs incompatible with macOS Sierra. Apple stated at WWDC 2017 that any Mac that can run macOS Sierra can also run macOS High Sierra, so that means that the list of incompatible Macs has not changed. For more details, see below the jump:

Here’s the list of Mac models which are incompatible with macOS High Sierra:

To create a smart group that contains the list of incompatible Macs, I’ve updated the smart group XML file I created last year for macOS Sierra. The smart group XML file is available below:

This smart group can be imported into a Jamf Pro server via the API. To upload it to a JSS server using the API, download the XML file to a convenient location, then run the command shown below (substituting as appropriate):

curl -skfu username:password https://jamfpro.server.here:8443/JSSResource/computergroups/id/0 -T /path/to/filename.xml -X POST;

If the smart group was successfully uploaded, you should next see output similar to that shown below:

A new smart group named Macs incompatible with macOS High Sierra should also now be present on the Jamf Pro server.

Screen Shot 2017 08 29 at 10 34 33 AM


APFS preparation and macOS High Sierra

$
0
0

As part of the pre-release announcements about macOS High Sierra, Apple released the following KBase article:

Apple makes a number of statements about APFS and its effects in this KBase article, but what do they all mean? I’m going to try to clarify while staying on the right side of Apple’s NDA. For more details, see below the jump.

APFS conversion criteria

  • Question: What kind of drives will be converted to APFS?
  • Answer:

Screen Shot 2017 09 07 at 5 00 58 PM

  • Question: If the drive qualifies, is the HFS+ -> APFS conversion automatic when I upgrade to High Sierra?
  • Answer: Yes

APFS compatibility

  • Question: Can you read and write to an HFS+ formatted drive while booted from an APFS formatted drive?
  • Answer: Yes
  • Question: Can you read and write to an APFS-formatted drive while booted from an HFS+ drive?
  • Answer:
    • On macOS High Sierra and later: Yes
    • On older versions of macOS, OS X and Mac OS X: No

APFS and FileVault

  • Question: Can a FileVault-encrypted drive be converted to APFS as part of the the macOS High Sierra upgrade process?
  • Answer: Yes. If the drive qualifies for the conversion process, the encrypted drive will be converted from HFS+ to APFS as part of the macOS High Sierra upgrade process.
    • As part of the conversion process, the encrypted Core Storage volume will be removed from the drive and the drive will have APFS’s native encryption activated.

APFS and Boot Camp

  • Question: Can I run Windows using Boot Camp on an APFS boot drive?
  • Answer: Yes. However, Windows will not have the necessary driver support to read or write to APFS formatted drives.

APFS and file sharing

  • Question: Can I enable AFP file sharing to share directories stored on an APFS drive?
  • Answer: No. SMB file sharing will need to be used.
  • Question: What file sharing protocols can share directories stored on an APFS drive?
  • Answer: SMB and NFS

APFS and Time Machine

  • Question: Do I need to change anything in Time Machine to back up an APFS drive?
  • Answer: No.
  • Question: Do I need to change anything in Time Machine to back up an APFS boot drive?
  • Answer: No.
  • Question: Can I use AFP to set up Time Machine share points on an APFS drive?
  • Answer: No, AFP file sharing won’t work on an APFS drive. Use SMB file sharing instead.


Changing local account passwords may cause new login keychain to be silently generated on macOS High Sierra

$
0
0

As part of my testing of macOS High Sierra, I’ve noticed that login behavior has changed for local accounts, in cases where the password of the login keychain is different from the password of the account logging in.

On macOS Sierra, the following behavior occurs when the password of the login keychain is different from the password of the local account logging in:

1. The login process pauses
2. You’re prompted to continue login, create a new keychain, or update the existing keychain password.

Screen Shot 2017 09 23 at 4 46 06 PM

3. If you choose to update the existing keychain password, you enter the keychain’s current password (which is usually the account’s former password.)

Screen Shot 2017 09 23 at 4 46 21 PM

4. The login process proceeds and the desktop comes up.

On macOS High Sierra, the following behavior occurs when the password of the login keychain is different from the password of the local account logging in:

1. The login keychain with the different password is renamed to login_renamed_number_goes_here.keychain-db and stored in ~/Library/Keychains.

Screen Shot 2017 09 23 at 8 01 46 PM

2. A new login keychain is created in ~/Library/Keychains. The new login keychain is named login.keychain-db and uses the password of the local account logging in.

Screen Shot 2017 09 23 at 8 01 50 PM

Note: This is behavior I’ve observed for local accounts only. I have not been able to test with network accounts, like Active Directory mobile accounts.

Update 9-26-2017: This behavior was addressed in the betas for Active Directory mobile accounts:

The reason why this behavior is problematic is that anything stored in the former login keychain is not transferred to the new login keychain. Saved passwords, certificates, and any other secrets stored in the now-former login keychain will not be present in the new login keychain. They will need to be manually copied, or re-saved into the new login keychain.

For more details, see below the jump.

I’ve been able to reproduce this behavior in the following ways:

1. Open Keychain Access
2. Under the Edit menu, select Change password for keychain “login”…

Screen Shot 2017 09 25 at 5 53 09 PM

3. Change the password of the keychain to be different from the account’s login password
4. Log out of the account
5. Log back in

1. Log in as a different account with administrator privileges
2. Open System Preferences
3. Select Users & Groups
4. Click the lock icon and provide administrator credentials when prompted.
5. Select the relevant account
6. Click the Reset Password button.

Screen Shot 2017 09 23 at 7 58 45 PM

7. Change the relevant account’s password.

Screen Shot 2017 09 23 at 7 59 20 PM

8. Log out of the different account.
9. Log in as the relevant account.


Using the macOS High Sierra OS installer’s startosinstall tool to avoid APFS conversion

$
0
0

As part of the upgrade process to macOS High Sierra, Apple has stated that certain drives will be converted from using the HFS+ filesystem to Apple’s new default filesystem, APFS. The conversion criteria is shown below:

Screen shot 2017 09 07 at 5 00 58 pm

For those Mac admins who don’t necessarily want to convert yet, there is a way to configure the macOS High Sierra OS installer to skip the APFS conversion. For more details, please see below the jump.

Apple includes a command line tool named startosinstall as part of the macOS High Sierra OS installer application, inside Install macOS High Sierra.app/Contents/Resources.

Screen Shot 2017 09 26 at 1 19 31 PM

This tool has several options, including a –converttoapfs option which allows control over the APFS conversion process.

To run an automated upgrade to macOS High Sierra, where the APFS conversion is skipped, please run the command shown below with root privileges:

/Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/startosinstall --applicationpath /Applications/Install\ macOS\ High\ Sierra.app --agreetolicense --converttoapfs NO --nointeraction

Note: The –nointeraction flag is an undocumented option to automate the installation process from the command line without additional requiring actions by the logged-in user.

To show what the process looks like when upgrading from macOS Sierra, please see below for a video.

Note: This video has been edited to artificially reduce the amount of time the upgrade process takes to run. Run time of the pre-edited video was 19 minutes 38 seconds.


Using the macOS High Sierra OS installer’s startosinstall tool to install additional packages as post-upgrade tasks

$
0
0

Starting with macOS 10.12.4, Apple locked down the macOS installer to make it impossible to add non-Apple installer packages directly to the macOS Install .app without using NetInstall. However, there is a way to configure the macOS High Sierra OS installer to install additional packages as a post-upgrade task. For more details, please see below the jump.

Apple includes a command line tool named as part of the macOS High Sierra OS installer application, inside Install macOS High Sierra.app/Contents/Resources.

 Screen Shot 2017 09 26 at 1 19 31 PM

This tool has several options, including a –installpackage option which allows one or more packages stored on the Mac in question to be installed following the upgrade.

Something to be aware of is that if you want to add any additional packages, they must all be signed or unsigned distribution-style flat packages. This is a requirement that Apple first introduced for the OS X Yosemite installer and it still applies to macOS High Sierra. You can convert a component flat package to be a distribution-style flat packages by running the command below:

productbuild –package /path/to/component.pkg /path/to/distribution.pkg

To run an automated upgrade to macOS High Sierra, where two distribution-style flat packages stored in /Users/Shared are installed following the upgrade, please run the command shown below with root privileges:

/Applications/Install\ macOS\ High\ Sierra.app/Contents/Resources/startosinstall --applicationpath /Applications/Install\ macOS\ High\ Sierra.app --agreetolicense --installpackage /Users/Shared/installer_one.pkg --installpackage /Users/Shared/installer_two.pkg --nointeraction

Note: The –nointeraction flag is an undocumented option to automate the installation process from the command line without additional requiring actions by the logged-in user.

To show what the process looks like when upgrading from macOS Sierra, please see below for a video. In this example, I’m installing the latest Office 2016 installer following the upgrade.

Note: The video has been edited to artificially reduce the amount of time the upgrade and post-upgrade installation process takes to run. Run time of the pre-edited video was 32 minutes 57 seconds.


Cancelling an unwanted FileVault deferred enablement

$
0
0

There are sometimes occasions when FileVault deferred encryption has been enabled for a particular Mac and then needs to be turned off. Since FileVault is not yet turned on at this point, there is no obvious way to turn off this deferred enablement.

However, it is possible to turn off a deferred enablement if needed. For more details, please see below the jump.

Detecting if a deferred enablement is active

A. Using the fdesetup command line tool

To check for a deferred enablement using the fdesetup command line tool, run the following command:

fdesetup status

If a deferred enablement is active, it should report this along with identifying the enabled user (if one has been selected.)

Screen Shot 2018 03 11 at 9 18 50 PM

B. Checking for /Library/Preferences/com.apple.fdesetup.plist

When a deferred enablement is active, a com.apple.fdesetup.plist file should be present in /Library/Preferences. This file will identify the path of the plist file which will store the the recovery key information, along with identifying the enabled user (if one has been selected.)

 

Screen Shot 2018 03 11 at 8 57 15 PM

The contents of the file should appear similar to what is shown below:

 

 

Turning off a deferred enablement

To turn off an active deferred enablement, please use the following procedure:

1. Run the following command with root privileges.

fdesetup disable

Note: The fdesetup output will report that FileVault is already off and not mention anything about the deferred enablement.

Screen Shot 2018 03 11 at 9 10 00 PM

 

2. Reboot the Mac.

3. After the reboot, run the following command:

fdesetup status

It should report the FileVault is off and not include information about a deferred enablement.

Screen Shot 2018 03 11 at 9 18 15 PM

This procedure should also remove the /Library/Preferences/com.apple.fdesetup.plist file. If the com.apple.fdesetup.plist file is still present following the reboot, remove the /Library/Preferences/com.apple.fdesetup.plist file and reboot again.

Screen Shot 2018 03 11 at 8 57 15 PM

New automated restart option added to macOS 10.13.4’s softwareupdate command line tool

$
0
0

With the release of macOS 10.13.4, Apple has added a new option to the softwareupdate command line tool. As part of the installation options, softwareupdate now includes the option to automatically restart or shutdown (as appropriate) following the installation of updates that need a restart or shutdown to complete properly.

-R | --restart		Automatically restart (or shut down) if required to complete installation.

Screen Shot 2018 03 09 at 4 24 17 PM

 

As an example, to use the new option to restart if needed after installing all available updates, please run the command shown below with root privileges:

softwareupdate --install --all --restart

In the event that no updates require a restart or shutdown, the Mac is not restarted.

Screen Shot 2018 03 09 at 4 18 59 PM

Viewing all 480 articles
Browse latest View live