Skip to content

Commit

Permalink
Resolve issues with key/cert and saml authorization
Browse files Browse the repository at this point in the history
  • Loading branch information
grzegorz-gutowski committed Mar 14, 2024
1 parent e8767bf commit 412a3b5
Show file tree
Hide file tree
Showing 17 changed files with 600 additions and 192 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ __pycache__
/dist/
/openvpn3-indicator
/tests/.vagrant
/tests/configurations/client_connexa.ovpn
5 changes: 4 additions & 1 deletion scripts/build_executable
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ assert directory.is_dir()

header = b'#!/usr/bin/env python3\n'

binary = subprocess.run(['zip', '-', '--recurse-paths', '-9', '.', ], cwd=directory, stdout=subprocess.PIPE).stdout
binary = subprocess.run(
['zip', '-', '--recurse-paths', '-9', '.', ],
cwd=directory, stdout=subprocess.PIPE
).stdout

executable.write_bytes(header + binary)
executable.chmod(0o755)
9 changes: 6 additions & 3 deletions src/openvpn3_indicator/__init__.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# vim:ts=4:sts=4:sw=4:expandtab

#
# openvpn3-indicator - Simple GTK indicator GUI for OpenVPN3.
# openvpn3-indicator - Simple indicator application for OpenVPN3.
# Copyright (C) 2024 Grzegorz Gutowski <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it
Expand All @@ -24,7 +24,7 @@
import sys
import traceback

from openvpn3_indicator.about import *
from openvpn3_indicator.about import APPLICATION_NAME
from openvpn3_indicator.application import Application

###
Expand All @@ -33,14 +33,17 @@
#
###


def main():
try:
import setproctitle
setproctitle.setproctitle(f'{APPLICATION_NAME}')
except ImportError:
pass
logging.debug(traceback.format_exc())
logging.error('Failed to import setproctitle module')
application = Application()
application.run(sys.argv)


if __name__ == '__main__':
main()
14 changes: 12 additions & 2 deletions src/openvpn3_indicator/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# vim:ts=4:sts=4:sw=4:expandtab

#
# openvpn3-indicator - Simple GTK indicator GUI for OpenVPN3.
# openvpn3-indicator - Simple indicator application for OpenVPN3.
# Copyright (C) 2024 Grzegorz Gutowski <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it
Expand All @@ -20,8 +20,18 @@
# If not, see <https://www.gnu.org/licenses/>.
#


APPLICATION_NAME = 'openvpn3-indicator'
APPLICATION_DESCRIPTION = 'OpenVPN3 Indicator'
APPLICATION_TITLE = 'OpenVPN3 Indicator'
APPLICATION_ID = 'net.openvpn.openvpn3_indicator'
APPLICATION_AUTHORS = [
'Grzegorz Gutowski <[email protected]>',
]
APPLICATION_URL = 'https://github.com/OpenVPN/openvpn3-indicator'
APPLICATION_VERSION = '0.1'
APPLICATION_DESCRIPTION_SHORT = 'Simple indicator application for OpenVPN3'
APPLICATION_DESCRIPTION_LONG = '''
This is a simple indicator application that controls OpenVPN3 tunnels.
It is based on D-Bus interface provided by OpenVPN3 Linux client.
It is a temporary solution until Network Manager supports OpenVPN3.
'''.strip()
214 changes: 71 additions & 143 deletions src/openvpn3_indicator/application.py

Large diffs are not rendered by default.

84 changes: 53 additions & 31 deletions src/openvpn3_indicator/credential_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# vim:ts=4:sts=4:sw=4:expandtab

#
# openvpn3-indicator - Simple GTK indicator GUI for OpenVPN3.
# openvpn3-indicator - Simple indicator application for OpenVPN3.
# Copyright (C) 2024 Grzegorz Gutowski <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it
Expand All @@ -24,54 +24,63 @@
import secretstorage
import traceback

from openvpn3_indicator.about import *
from openvpn3_indicator.about import APPLICATION_NAME, APPLICATION_TITLE

###
#
# CredentialStore
#
###


class CredentialStore:

@property
def application_id(self):
return self._application_id
def application_name(self):
return self._application_name

@property
def application_description(self):
return self._application_description

@property
def secret_collection(self):
if self._secret_collection is None:
try:
secret_connection = secretstorage.dbus_init()
self._secret_collection = secretstorage.get_default_collection(secret_connection)
except:
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to connect with Secret Storage')
logging.error('Failed to connect with Secret Storage')
return self._secret_collection

@property
def secret_collection_unlocked(self):
collection = self.secret_collection
if collection is not None:
if collection.is_locked():
try:
collection.unlock()
except:
logging.info('Unlocked Secret Storage')
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to unlock Secret Storage')
logging.error('Failed to unlock Secret Storage')
collection = None
return collection

def attrs(self):
attrs = dict()
attrs['application'] = self.application_id
attrs['application'] = self.application_name
return attrs

def __init__(self, application_id=APPLICATION_NAME, application_description=APPLICATION_DESCRIPTION):
self._application_id = application_id
def __init__(self, application_name=APPLICATION_NAME, application_description=APPLICATION_TITLE):
self._application_name = application_name
self._application_description = application_description
self._secret_collection = None

def __getitem__(self, key):
return self.Credentials(self, key)

def keys(self):
collection = self.secret_collection_unlocked
result = set()
Expand All @@ -81,28 +90,32 @@ def keys(self):
config = item.get_attributes().get('config', None)
if config is not None:
result.add(config)
except:
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to list from Secret Storage')
logging.error('Failed to list Secret Storage')
return sorted(list(result))

class Credentials:

@property
def parent(self):
return self._parent

@property
def config_id(self):
return self._config_id

def __init__(self, parent, config_id):
self._parent = parent
self._config_id = str(config_id)

def attrs(self, key=None):
attrs = dict()
attrs['application'] = self.parent.application_id
attrs = self.parent.attrs()
attrs['config'] = self.config_id
if key is not None:
attrs['key'] = str(key)
return attrs

def label(self, key):
key = str(key)
return f'{self.parent.application_description} {self.config_id} {key}'
Expand All @@ -114,39 +127,48 @@ def __setitem__(self, key, item):
if collection:
try:
label = self.label(key)
collection.create_item(
label,
self.attrs(key),
bytes(str(item), 'utf-8'),
replace=True)
logging.debug(f'Storing secret {label}')
except:
if item is not None:
collection.create_item(
label,
self.attrs(key),
bytes(str(item), 'utf-8'),
replace=True)
logging.info(f'Stored secret {label} in Secret Storage')
else:
for item in collection.search_items(self.attrs(key)):
item.delete()
logging.info(f'Removed secret {label} from Secret Storage')
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to write to Secret Storage')
logging.error('Failed to write to Secret Storage')

def __getitem__(self, key):
key = str(key)
collection = self.parent.secret_collection_unlocked
if collection:
try:
items = list(collection.search_items(self.attrs(key)))
if len(items) > 1:
label = self.label(key)
log.error(f'There are multiple entries for {label} in Secret Storage')
logging.warning(f'There are multiple entries for {self.label(key)} in Secret Storage')
if len(items) > 0:
return str(items[0].get_secret(), 'utf-8')
except:
logging.info(f'Retrieved secret {self.label(key)} from Secret Storage')
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to read from Secret Storage')
logging.error('Failed to read from Secret Storage')

def __delitem__(self, key):
key = str(key)
collection = self.parent.secret_collection_unlocked
if collection:
try:
for item in collection.search_items(self.attrs(key)):
item.delete()
except:
logging.info(f'Removed secret {self.label(key)} from Secret Storage')
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to delete from Secret Storage')
logging.error('Failed to delete from Secret Storage')

def keys(self):
collection = self.parent.secret_collection_unlocked
result = set()
Expand All @@ -156,7 +178,7 @@ def keys(self):
key = item.get_attributes().get('key', None)
if key is not None:
result.add(key)
except:
except: # TODO: Catch only expected exceptions
logging.debug(traceback.format_exc())
logging.error(f'Failed to list from Secret Storage')
logging.error('Failed to list Secret Storage')
return sorted(list(result))
44 changes: 44 additions & 0 deletions src/openvpn3_indicator/dialogs/about.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python3
# vim:ts=4:sts=4:sw=4:expandtab

#
# openvpn3-indicator - Simple indicator application for OpenVPN3.
# Copyright (C) 2024 Grzegorz Gutowski <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License,
# or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, GObject, Gtk, Gio

from openvpn3_indicator.about import APPLICATION_NAME, APPLICATION_TITLE, APPLICATION_VERSION, APPLICATION_AUTHORS, APPLICATION_URL, APPLICATION_DESCRIPTION_SHORT


def construct_about_dialog():
dialog = Gtk.AboutDialog()
dialog.set_position(Gtk.WindowPosition.CENTER)
dialog.set_keep_above(True)
dialog.set_icon_name(APPLICATION_NAME)

dialog.set_program_name(APPLICATION_TITLE)
dialog.set_logo_icon_name(APPLICATION_NAME)
dialog.set_version(APPLICATION_VERSION)
dialog.set_comments(APPLICATION_DESCRIPTION_SHORT)
dialog.set_website(APPLICATION_URL)
dialog.set_license_type(Gtk.License.AGPL_3_0)
dialog.set_authors(APPLICATION_AUTHORS)
dialog.show_all()
return dialog
Loading

0 comments on commit 412a3b5

Please sign in to comment.