Skip to content

Commit 5d1afe7

Browse files
committed
Add otp-agent example
1 parent 307cbe2 commit 5d1afe7

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

examples/otp-agent

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/python3
2+
#
3+
# Automate vpn connections that require a one-time password.
4+
# Requirements:
5+
# - secretstorage (find on pypi)
6+
# - pyotp (likewise)
7+
#
8+
# usage: ./otp-agent name-of-connection
9+
#
10+
# The connection will be activated and when networkmanager asks for a secret,
11+
# it will be provided. If the secret isn't known yet, it will be asked and
12+
# stored with the secretstorage api (so in e.g. your gnome keyring)
13+
14+
import dbus.mainloop.glib
15+
from gi.repository import GObject
16+
import NetworkManager
17+
import pyotp
18+
import traceback
19+
import secretstorage
20+
import sys
21+
22+
def main():
23+
print("Connecting to %s" % sys.argv[1])
24+
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
25+
loop = GObject.MainLoop()
26+
agent = SecretAgent(loop)
27+
for connection in NetworkManager.Settings.ListConnections():
28+
settings = connection.GetSettings()['connection']
29+
if settings['id'] == sys.argv[1]:
30+
NetworkManager.NetworkManager.ActivateConnection(connection, "/", "/")
31+
loop.run()
32+
break
33+
else:
34+
print("Connection %s not found" % sys.argv[1])
35+
36+
class SecretAgent(NetworkManager.SecretAgent):
37+
def __init__(self, loop):
38+
self.loop = loop
39+
self.collection = secretstorage.get_default_collection(secretstorage.dbus_init())
40+
super(SecretAgent, self).__init__('net.seveas.otp-agent')
41+
42+
def GetSecrets(self, settings, connection, setting_name, hints, flags):
43+
try:
44+
print("NetworkManager is asking us for a secret")
45+
if setting_name != 'vpn':
46+
return {}
47+
attrs = {
48+
'xdg:schema': 'net.seveas.otp-agent',
49+
'hostname': settings['vpn']['data']['remote'],
50+
}
51+
items = list(self.collection.search_items(attrs))
52+
if not items:
53+
print("No secrets found yet, asking user")
54+
secret = input("Enter secret code for %s: " % settings['vpn']['data']['remote'])
55+
self.collection.create_item(settings['vpn']['data']['remote'], attrs, secret)
56+
items = list(self.collection.search_items(attrs))
57+
else:
58+
print("Found secret key, generating otp code")
59+
secret = items[0].get_secret().decode('ascii')
60+
otp = pyotp.TOTP(secret).now()
61+
print("otp code: %s" % otp)
62+
return {setting_name: {'secrets': {'password': otp}}}
63+
except:
64+
import traceback
65+
traceback.print_exc()
66+
return {}
67+
finally:
68+
self.loop.quit()
69+
70+
if __name__ == '__main__':
71+
main()

0 commit comments

Comments
 (0)