diff --git a/subiquitycore/snap.py b/subiquitycore/snap.py
new file mode 100644
index 00000000..1ef667c2
--- /dev/null
+++ b/subiquitycore/snap.py
@@ -0,0 +1,33 @@
+# Copyright 2024 Canonical, Ltd.
+#
+# 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 (at your option) 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 .
+
+import os
+
+
+# Returns true if the current execution environment is inside a snap.
+def is_snap():
+ return os.getenv("SNAP_CONFINEMENT") is not None
+
+
+# Returns true if the current execution environment is inside a strictly
+# confined snap.
+def is_snap_strictly_confined():
+ return os.getenv("SNAP_CONFINEMENT", "classic") == "strict"
+
+
+# Returns the snap name if the current execution context is inside a snap,
+# otherwise None.
+def snap_name():
+ return os.getenv("SNAP_INSTANCE_NAME")
diff --git a/subiquitycore/tests/test_snap.py b/subiquitycore/tests/test_snap.py
new file mode 100644
index 00000000..f1fcf22d
--- /dev/null
+++ b/subiquitycore/tests/test_snap.py
@@ -0,0 +1,58 @@
+# Copyright 2024 Canonical, Ltd.
+#
+# 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 (at your option) 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 .
+
+import unittest
+from unittest.mock import patch
+
+from subiquitycore import snap
+
+
+class TestSnap(unittest.TestCase):
+ @patch("os.getenv", return_value=None)
+ def test_is_snap(self, os_getenv):
+ self.assertFalse(snap.is_snap())
+ os_getenv.assert_called_with("SNAP_CONFINEMENT")
+ os_getenv.reset_mock()
+
+ os_getenv.return_value = "strict"
+ self.assertTrue(snap.is_snap())
+ os_getenv.assert_called_with("SNAP_CONFINEMENT")
+ os_getenv.reset_mock()
+
+ os_getenv.return_value = "classic"
+ self.assertTrue(snap.is_snap())
+ os_getenv.assert_called_with("SNAP_CONFINEMENT")
+ os_getenv.reset_mock()
+
+ @patch("os.getenv", return_value=None)
+ def test_snap_confinement(self, os_getenv):
+ self.assertFalse(snap.is_snap_strictly_confined())
+ os_getenv.assert_called_with("SNAP_CONFINEMENT", "classic")
+ os_getenv.reset_mock()
+
+ os_getenv.return_value = "strict"
+ self.assertTrue(snap.is_snap_strictly_confined())
+
+ os_getenv.return_value = "classic"
+ self.assertFalse(snap.is_snap_strictly_confined())
+
+ @patch("os.getenv", return_value=None)
+ def test_snap_name(self, os_getenv):
+ self.assertIsNone(snap.snap_name())
+ os_getenv.assert_called_with("SNAP_INSTANCE_NAME")
+ os_getenv.reset_mock()
+
+ os_getenv.return_value = "console-conf"
+ self.assertEqual(snap.snap_name(), "console-conf")