I’m writing a little script/app that will turn off all network interfaces and then launch Google Drive and then turn the network interfaces back on.
This is for my olde macbook pro running El Capitan which if there is an active network connection, Google Drive balks and refuses to launch complaining about how I need to update the OS first, which I can’t. The macbook pro can’t go beyond 10.11.6.
I’ve discovered that if i turn off all internet connections, then launch Google Drive, then reenable internet access, Google Drive basically still functions.
For Wi-Fi I can use
do shell script “networksetup -setairportpower en1 off”
and
do shell script “networksetup -setairportpower en1 on”
and they don’t require a username/password.
However for Ethernet, I’m using
do shell script “networksetup -setnetworkserviceenabled Ethernet off” user name “me” password “mypass” with administrator privileges
and
do shell script “networksetup -setnetworkserviceenabled Ethernet on” user name “me” password “mypass” with administrator privileges
I’ve been tinkering with using PrefsStorageLib to store the username and password, but that’s not secure, and I’m thinking I’ll share this effort once it works.
But it’d be way better to use the keychain, but that’s a complete mystery to me.
Can it be done from in an Applescript Applet ?
(Access the keychain safely / securely ?)
Here is a snippet I have in use for a long time now …
property KeychainPasswordName : "YOUR_KEYCHAIN_PASSWORD" -- name of your password item in the Keychain
set my_password to getPassword(KeychainPasswordName)
set my_username to getUsername()
-- Retrieve the administror password you saved on your Keychain
on getPassword(keychainItemName)
local password
set password to do shell script ("/usr/bin/security 2>&1 >/dev/null find-generic-password -gl " & quoted form of keychainItemName & " | cut -c 11-99 | sed 's/\"//g'")
if password contains "could not be found in the keychain" or password as string is equal to "" then
display alert "Password not found in the keychain" message "Certain tasks in this script need the administrator password to work.
You must create a new password in the OS X Keychain with a custom name, and set it with your administrator password, then edit this script." as critical
error "Password could not be found in the keychain."
else
return password
end if
end getPassword
-- Get the short username (name of your home folder)
on getUsername()
#tell application "System Events" to return the name of current user
short user name of (system info)
end getUsername
as far as I am aware this code works without issues…
Is there a way to just request access to the human’s “user name” & “password” which will likely be an Administrator username/password for the Mac ?
It’s easy enough to tell the user to create a new entry in Keychain Access for my Applet so it can know what the user name and password of an admin account is, but there’s going to be that percentage that just can’t do it right, and so the Applet won’t work as expected…
ps: the getUsername function needs a small correction
– Get the short username (name of your home folder)
on getUsername()
# tell application “System Events” to return the name of current user
return short user name of (system info) ## Added the return
end getUsername
However, the frameworks used are from 2015/16 and therefore do not run on an Apple Silicon. Perhaps someone could recompile them (unfortunately I failed).
About the SSKeychain Framework- it might be unmaintained but I can confirm that it is still usable with Monterey on an Intel Processor based Mac.
I have to say thank you to you as well - if you’ve not posted in your blog about these two Frameworks - we might possibly never known about their existence. Thank you
Why has no one suggested using the excellent “Usable Keychain Scripting” app written by Daniel Jalkut, of Red Sweater and FastScripts fame?
Though written in 2006, it still works fine here. But then, I am still running Big Sur. Can’t swear it works on later macOS versions. To try it, grab it here: Usable Keychain Scripting –
StanC, wouldn’t I have to bundle “Usable Keychain Scripting” with my Applet though, if I used “Usable Keychain Scripting” and manage to give away at least one copy of my Applet ??
The bit about “personal needs” may rule out giving away or selling it bundled in your software. However, the intent of the word “personal” is not clear. Maybe Daniel himself could clarify?
Which leads inevitably to the larger problem of a moribund language abandoned by those in control of the system of which it’s an almost completely neglected part.
So many of the technical discussions here can be regarded as details of the decline and fall of macOS automation. Forgive the digression, but has any organized group ever make a serious attempt to address the larger problem? AppleScript has been in conspicuous decline for more years than I can easily recall.
The question of keychain access has nothing to do with AppleScript and whether the language is maintained or not!
I have posted a Sample above with which you can create, read and delete a keychain entry with applescript. You can also access other entries for which the process has access:
set keychain to current application's DTKeychain's sharedInstance()
set query to current application's DTKeychainGenericPassword's keychainItemQueryForService:(missing value) account:(missing value)
set {itemList, errorRes} to my (keychain's keychainItemsMatchingQuery:query |error|:(reference))
repeat with i from 0 to (itemList's |count|()) - 1
set theItem to (itemList's objectAtIndex:i)
try
log ("Service name: " & theItem's service as text) & " - Account name: " & theItem's account as text
end try
end repeat
… and then even retrieve the passwords for the respective entry:
set keychain to current application's DTKeychain's sharedInstance()
set query to current application's DTKeychainGenericPassword's keychainItemQueryForService:("Service name") account:("Account name")
set {itemList, errorRes} to my (keychain's keychainItemsMatchingQuery:query |error|:(reference))
if itemList's |count|() > 0 then
set pass to itemList's firstObject()
if my (keychain's retrieveSecuredDataForKeychainItem:pass |error|:(missing value)) then
set thePassword to pass's |password| as text
end if
end if
You can’t do more with other languages, because not every process (or app) has access to every password in the keychain, and that’s a good thing.
@furbies:
Which user name and password do you want to retrieve from the keychain? One you have stored yourself with your applet? - That works (see the Sample). Or the system user name and password? - That would be bad if that were possible.