permissions: update netplan configs to 0600

Since netplan 0.106.1, Netplan YAMLs should have file permissions
with mode 0o600 (owner RW only) and root owner.
This commit is contained in:
Chris Peterson 2024-02-13 16:36:11 -08:00
parent 24f48f0d87
commit 9ecc4060b9
3 changed files with 44 additions and 2 deletions

View File

@ -62,7 +62,8 @@ class NetworkModel(CoreNetworkModel):
} }
} }
else: else:
# Separate sensitive wifi config from world-readable config # Separate sensitive wifi config from potentially shared config
# e.g. via apport
wifis = netplan["network"].pop("wifis", None) wifis = netplan["network"].pop("wifis", None)
r = { r = {
"write_files": { "write_files": {
@ -73,11 +74,13 @@ class NetworkModel(CoreNetworkModel):
"subiquity-disable-cloudinit-networking.cfg" "subiquity-disable-cloudinit-networking.cfg"
), ),
"content": "network: {config: disabled}\n", "content": "network: {config: disabled}\n",
"permissions": "0600",
}, },
# World-readable netplan without sensitive wifi config # netplan without sensitive wifi config
"etc_netplan_installer": { "etc_netplan_installer": {
"path": "etc/netplan/00-installer-config.yaml", "path": "etc/netplan/00-installer-config.yaml",
"content": self.stringify_config(netplan), "content": self.stringify_config(netplan),
"permissions": "0600",
}, },
}, },
} }
@ -88,6 +91,7 @@ class NetworkModel(CoreNetworkModel):
"wifis": wifis, "wifis": wifis,
}, },
} }
# sensitive wifi config
r["write_files"]["etc_netplan_installer_wifi"] = { r["write_files"]["etc_netplan_installer_wifi"] = {
"path": "etc/netplan/00-installer-config-wifi.yaml", "path": "etc/netplan/00-installer-config-wifi.yaml",
"content": self.stringify_config(netplan_wifi), "content": self.stringify_config(netplan_wifi),

View File

@ -42,3 +42,13 @@ class TestNetworkModel(unittest.IsolatedAsyncioTestCase):
with mock.patch("subiquity.models.network.arun_command") as arun: with mock.patch("subiquity.models.network.arun_command") as arun:
arun.side_effect = subprocess.CalledProcessError(1, [], None, "error") arun.side_effect = subprocess.CalledProcessError(1, [], None, "error")
self.assertFalse(await self.model.is_nm_enabled()) self.assertFalse(await self.model.is_nm_enabled())
async def test_write_netplan_permissions(self):
"""Assert correct netplan config permissions
Since netplan 0.106.1, Netplan YAMLs should have file
permissions with mode 0o600 (root/owner RW only).
"""
config = self.model.render()
for file in config["write_files"].values():
self.assertEqual(file["permissions"], "0600")

View File

@ -13,14 +13,42 @@
# You should have received a copy of the GNU Affero General Public License # You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from unittest.mock import ANY, Mock, patch
import jsonschema import jsonschema
from jsonschema.validators import validator_for from jsonschema.validators import validator_for
from subiquity.server.controllers.network import NetworkController from subiquity.server.controllers.network import NetworkController
from subiquitycore.tests import SubiTestCase from subiquitycore.tests import SubiTestCase
from subiquitycore.tests.mocks import make_app
class TestNetworkController(SubiTestCase): class TestNetworkController(SubiTestCase):
def setUp(self):
app = make_app()
app.note_file_for_apport = Mock()
app.opts.output_base = self.tmp_dir()
app.opts.project = "subiquity"
self.controller = NetworkController(app)
self.controller.model.render_config = Mock(return_value=dict())
self.controller.model.stringify_config = Mock(return_value="")
def test_netplan_permissions(self):
"""Assert correct netplan config permissions
Since netplan 0.106.1, Netplan YAMLs should have file
permissions with mode 0o600 (root/owner RW only).
"""
with (
patch("os.getuid", return_value=0),
patch("os.chmod") as mock_chmod,
patch("os.chown") as mock_chown,
):
self.controller._write_config()
mock_chmod.assert_called_with(ANY, 0o600)
mock_chown.assert_called_with(ANY, 0, 0)
def test_valid_schema(self): def test_valid_schema(self):
"""Test that the expected autoinstall JSON schema is valid""" """Test that the expected autoinstall JSON schema is valid"""