op commands failing from cronjob/bash script
I suspect the following is more of a Linux question, but maybe someone here has had the same issue already.
I have a Python script that syncs "Secrets" (user/pass combos) from an IPAM software called NetBox to 1Pass. To launch the .py
script I am using another bash script that is regularly called by a cronjob. When I launch the bash script from the command line, everything works completely fine. However, when launching the bash script (using the full path) from a cronjob, the script fails to run the op
commands correctly. I'm thinking this is related to the eval
and environment variable in some way.
One thing to note, for testing, in order to automate inputting the Master Password for signin
, I have another script from elsewhere that temporarily decrypts the password, adds a plaintext file in base64 named op.mp
and then deletes it after the sync script has run. You'll see that in the first two lines copied below.
cat /home/testuser/nornir/auth/op.mp | base64 --decode | op signin eval $(cat /home/testuser/nornir/auth/op.mp | base64 --decode | op signin testuser) op delete vault netbox op create vault --allow-admins-to-manage true --description "Synced entries from NetBox" netbox /usr/bin/python3 /home/testuser/nornir/update_1pass.py if [ $? -eq 0 ]; then logger --rfc3164 -P 514 -n 10.10.10.10 "NetBox device secrets have been synced with 1Password" else logger --rfc3164 -P 514 -n 10.10.10.10 "Failed to sync NetBox device secrets with 1Password" fi
Any idea what could be causing this to fail specifically by launching the bash/python script via crontab/cronjob? Is there another recommended way to do this?
1Password Version: 1.4.0
Extension Version: Not Provided
OS Version: 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1+deb10u1 (20
Sync Type: Not Provided
Comments
-
Well, I figured it out. I added all the
op
commands directly into the python script itself usingos.system()
You can disregard/delete this post!
0 -
Hi @CoreyPaul ! I'm glad you were able to figure this out on your own.
One reason why it might fail is that it might not find the
op
binary since PATH might be set to a different value than in your "normal" shell. But if that was the case then your solution wouldn't work either.What errors did you originally get?
0 -
@CoreyPaul - Any chance you would be willing to share your python script. I want to do the same between my iCloud Keychain passwords (mostly Safari) and 1Password. Most of my devices are iOS or Mac but I do have a work laptop with Windows and trying to find a way to synchronize.
0 -
@jr_jeff no problem, pasted below is the relevant portion, only omitting all of my custom NetBox API calls that pulls together a list of devices/secrets.
import subprocess import requests import json import os import csv # # Sign in to 1Password CLI # op_signin = """ cat /home/testuser/nornir/auth/op.mp | base64 --decode | op signin sleep 2 OP_SESSION_testuser=$(cat /home/testuser/nornir/auth/op.mp | base64 --decode | op signin testuser --raw) export OP_SESSION_testuser sleep 2 op delete vault netbox sleep 2 op create vault --allow-admins-to-manage true --description "Synced entries from NetBox" netbox sleep 2 """ os.system(op_signin) # # Create entries in 1Password # with open("devices.csv") as f: for line in csv.DictReader( f, fieldnames=("device_name", "device_ip", "username", "password") ): devices = line cmd = ( "SESSION_KEY=$(cat /home/testuser/nornir/auth/op.mp | base64 --decode | op signin testuser --raw) \n" + "op create item login title=" + devices["device_name"] + " username=" + devices["username"] + " password=" + "'" + devices["password"] + "'" + " --url=" + devices["device_ip"] + " --vault netbox" + " --session $SESSION_KEY" ) os.system(cmd) # # Delete files and clean up # os.system("op signout") os.system("rm -rf devices.csv") os.system( 'logger --rfc3164 -P 514 -n 10.10.10.100 "Finished syncing NetBox secrets to 1Password"' )
Couple things to note here:
devices.csv
is simply a comma separated file with one line per device listingdevice_name,device_ip,username,password
. This file is created from my IPAM software by the script and then deleted afterwords. You would need to write a separate script that creates a similar file for your own devices.The variable
op_signin
is a list of commands launched byos.system(op_signin)
. You'll see that I am deleting and recreating my vault callednetbox
everytime the script is launched (nightly). This completely rebuilds the vault and assigns the vault/items new UUIDs every time. I found this more convenient than checking for prexisting items everytime. It also requires that all my other scripts never store UUIDs and can only poll theop
command line at runtime by item/device name.op.mp
is the 1Pass master password for the account being used. It's just a text file with the password stored as a base64 string. This file is created by the root user moments before launching the script. What you don't see is another file,/auth/op.mp.encrypted
that is decrypted by the root user and used to create the decryptedop.mp
file, which is thenchmod
to allow testuser to access it. After the python script is finished, the root user then deletes theop.mp
leaving only the inaccessibleop.mp.encrypted
file to remain. I know this is a long away around proper security, but it separates user access and at least allows a somewhat obfuscated way of storing the 1Pass master password on a server and automating all of this with cronjobs.
0 -
Thanks for sharing that script and info @CoreyPaul !
Much appreciated :+1:0