Install system certs in snap accessible location

Ensure that updated system ca-certificates.crt file is copied into
a location within SNAP_COMMON so that snap based services can
use private CA certs.

Change-Id: Ie948a239e962ce9fdfc868b1741dcccb0711afb8
Related-Bug: 1724012
This commit is contained in:
James Page 2017-10-25 15:04:17 +01:00
parent 2b1a42c612
commit 575d729487
2 changed files with 66 additions and 0 deletions

View File

@ -2,6 +2,7 @@ import base64
import contextlib
import os
import random
import shutil
import string
import subprocess
@ -29,6 +30,8 @@ VIP_KEY = "vip"
CIDR_KEY = "vip_cidr"
IFACE_KEY = "vip_iface"
APACHE_SSL_VHOST = '/etc/apache2/sites-available/openstack_https_frontend.conf'
SYSTEM_CA_CERTS = '/etc/ssl/certs/ca-certificates.crt'
SNAP_CA_CERTS = '/var/snap/{}/common/etc/ssl/certs/ca-certificates.crt'
class OpenStackCharm(BaseOpenStackCharm,
@ -630,6 +633,7 @@ class HAOpenStackCharm(OpenStackAPICharm):
for path in cert_files}
if checksums != new_checksums and update_certs:
self.run_update_certs()
self.install_snap_certs()
def configure_ca(self, ca_cert, update_certs=True):
"""Write Certificate Authority certificate"""
@ -650,6 +654,22 @@ class HAOpenStackCharm(OpenStackAPICharm):
"""
subprocess.check_call(['update-ca-certificates', '--fresh'])
def install_snap_certs(self):
"""Install systems CA certificates for a snap
Installs the aggregated host system ca-certificates.crt into
$SNAP_COMMON/etc/ssl/certs for services running within a sandboxed
snap to consume.
Snaps should set the REQUESTS_CA_BUNDLE environment variable to
ensure requests based API calls use the updated system certs.
"""
if (os_utils.snap_install_requested() and
os.path.exists(SYSTEM_CA_CERTS)):
ca_certs = SNAP_CA_CERTS.format(self.primary_snap)
ch_host.mkdir(os.path.dirname(ca_certs))
shutil.copyfile(SYSTEM_CA_CERTS, ca_certs)
def update_peers(self, cluster):
"""Update peers in the cluster about the addresses that this unit
holds.

View File

@ -747,6 +747,7 @@ class TestHAOpenStackCharm(BaseOpenStackCharmTest):
def test_configure_ca(self):
self.patch_target('run_update_certs')
self.patch_target('install_snap_certs')
with utils.patch_open() as (mock_open, mock_file):
self.target.configure_ca('myca')
mock_open.assert_called_with(
@ -760,6 +761,49 @@ class TestHAOpenStackCharm(BaseOpenStackCharmTest):
self.check_call.assert_called_once_with(
['update-ca-certificates', '--fresh'])
def test_install_snap_certs(self):
self.patch_object(chm.os_utils, 'snap_install_requested',
return_value=True)
self.patch_object(chm.shutil, 'copyfile')
self.patch_object(chm.ch_host, 'mkdir')
self.patch_object(chm.os.path, 'exists', return_value=True)
self.target.snaps = ['mysnap']
self.target.install_snap_certs()
self.exists.assert_called_with('/etc/ssl/certs/ca-certificates.crt')
self.copyfile.assert_called_with(
'/etc/ssl/certs/ca-certificates.crt',
'/var/snap/mysnap/common/etc/ssl/certs/ca-certificates.crt',
)
self.mkdir.assert_called_with('/var/snap/mysnap/common/etc/ssl/certs')
self.snap_install_requested.reset_mock()
self.snap_install_requested.return_value = True
self.exists.reset_mock()
self.exists.return_value = False
self.copyfile.reset_mock()
self.mkdir.reset_mock()
self.target.install_snap_certs()
self.exists.assert_called_with('/etc/ssl/certs/ca-certificates.crt')
self.mkdir.assert_not_called()
self.copyfile.assert_not_called()
self.snap_install_requested.reset_mock()
self.snap_install_requested.return_value = False
self.exists.reset_mock()
self.exists.return_value = True
self.copyfile.reset_mock()
self.mkdir.reset_mock()
self.target.install_snap_certs()
self.exists.assert_not_called()
self.mkdir.assert_not_called()
self.copyfile.assert_not_called()
def test_update_central_cacerts(self):
self.patch_target('run_update_certs')
change_hashes = ['hash1', 'hash2']
@ -771,6 +815,8 @@ class TestHAOpenStackCharm(BaseOpenStackCharmTest):
return fake_hash_inner
self.patch_object(chm.ch_host, 'path_hash')
self.path_hash.side_effect = fake_hash(change_hashes)
self.patch_object(chm.os_utils, 'snap_install_requested',
return_value=False)
with self.target.update_central_cacerts(['file1']):
pass
self.run_update_certs.assert_called_with()