diff --git a/magnum/common/x509/operations.py b/magnum/common/x509/operations.py index 1b63b268d0..4cd21c116e 100644 --- a/magnum/common/x509/operations.py +++ b/magnum/common/x509/operations.py @@ -87,11 +87,14 @@ def _build_ca_extentions(): key_usage = x509.KeyUsage(False, False, False, False, False, True, False, False, False) key_usage = x509.Extension(key_usage.oid, True, key_usage) + extended_key_usage = x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]) + extended_key_usage = x509.Extension(extended_key_usage.oid, False, + extended_key_usage) basic_constraints = x509.BasicConstraints(ca=True, path_length=0) basic_constraints = x509.Extension(basic_constraints.oid, True, basic_constraints) - return [basic_constraints, key_usage] + return [basic_constraints, key_usage, extended_key_usage] def _generate_self_signed_certificate(subject_name, extensions, @@ -231,6 +234,29 @@ def sign(csr, issuer_name, ca_key, ca_key_password=None, return certificate +def generate_csr_and_key(common_name): + """Return a dict with a new csr and key.""" + key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + backend=default_backend()) + + csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ + x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, common_name), + ])).sign(key, hashes.SHA256(), default_backend()) + + result = { + 'csr': csr.public_bytes( + encoding=serialization.Encoding.PEM).decode("utf-8"), + 'key': key.private_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PrivateFormat.TraditionalOpenSSL, + encryption_algorithm=serialization.NoEncryption()).decode("utf-8"), + } + + return result + + def decrypt_key(encrypted_key, password): private_key = _load_pem_private_key(encrypted_key, password) diff --git a/magnum/drivers/common/templates/kubernetes/fragments/configure-kubernetes-master.sh b/magnum/drivers/common/templates/kubernetes/fragments/configure-kubernetes-master.sh index 08cf75070b..3dcb4ae509 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/configure-kubernetes-master.sh +++ b/magnum/drivers/common/templates/kubernetes/fragments/configure-kubernetes-master.sh @@ -42,7 +42,7 @@ else KUBE_API_ARGS="$KUBE_API_ARGS --tls-private-key-file=$CERT_DIR/server.key" KUBE_API_ARGS="$KUBE_API_ARGS --client-ca-file=$CERT_DIR/ca.crt" KUBE_API_ARGS="$KUBE_API_ARGS --tls-ca-file=${CERT_DIR}/ca.crt" - KUBE_API_ARGS="$KUBE_API_ARGS --service-account-key-file=${CERT_DIR}/server.key" + KUBE_API_ARGS="$KUBE_API_ARGS --service-account-key-file=${CERT_DIR}/service_account.key" KUBE_API_ARGS="$KUBE_API_ARGS --kubelet-certificate-authority=${CERT_DIR}/ca.crt --kubelet-client-certificate=${CERT_DIR}/server.crt --kubelet-client-key=${CERT_DIR}/server.key --kubelet-https=true" fi @@ -68,7 +68,7 @@ sed -i ' KUBE_CONTROLLER_MANAGER_ARGS="--leader-elect=true" KUBE_CONTROLLER_MANAGER_ARGS="$KUBE_CONTROLLER_MANAGER_ARGS $KUBECONTROLLER_OPTIONS" if [ -n "${ADMISSION_CONTROL_LIST}" ] && [ "${TLS_DISABLED}" == "False" ]; then - KUBE_CONTROLLER_MANAGER_ARGS="$KUBE_CONTROLLER_MANAGER_ARGS --service-account-private-key-file=$CERT_DIR/server.key --root-ca-file=$CERT_DIR/ca.crt" + KUBE_CONTROLLER_MANAGER_ARGS="$KUBE_CONTROLLER_MANAGER_ARGS --service-account-private-key-file=$CERT_DIR/service_account_private.key --root-ca-file=$CERT_DIR/ca.crt" fi if [ -n "$TRUST_ID" ]; then diff --git a/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh b/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh index 42f2323772..8ba16dad68 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh +++ b/magnum/drivers/common/templates/kubernetes/fragments/make-cert.sh @@ -169,6 +169,10 @@ EOF generate_certificates server ${cert_dir}/server.conf generate_certificates kubelet ${cert_dir}/kubelet.conf +# Generate service account key and private key +echo -e "${KUBE_SERVICE_ACCOUNT_KEY}" > ${cert_dir}/service_account.key +echo -e "${KUBE_SERVICE_ACCOUNT_PRIVATE_KEY}" > ${cert_dir}/service_account_private.key + # Common certs and key are created for both etcd and kubernetes services. # Both etcd and kube user should have permission to access the certs and key. groupadd kube_etcd diff --git a/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml b/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml index 01aff1d418..7e2b7bf1a3 100644 --- a/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml +++ b/magnum/drivers/common/templates/kubernetes/fragments/write-heat-params-master.yaml @@ -72,3 +72,5 @@ write_files: KUBEPROXY_OPTIONS="$KUBEPROXY_OPTIONS" KUBESCHEDULER_OPTIONS="$KUBESCHEDULER_OPTIONS" OCTAVIA_ENABLED="$OCTAVIA_ENABLED" + KUBE_SERVICE_ACCOUNT_KEY="$KUBE_SERVICE_ACCOUNT_KEY" + KUBE_SERVICE_ACCOUNT_PRIVATE_KEY="$KUBE_SERVICE_ACCOUNT_PRIVATE_KEY" diff --git a/magnum/drivers/heat/k8s_fedora_template_def.py b/magnum/drivers/heat/k8s_fedora_template_def.py index 16884f08ea..bfadd89aed 100644 --- a/magnum/drivers/heat/k8s_fedora_template_def.py +++ b/magnum/drivers/heat/k8s_fedora_template_def.py @@ -102,6 +102,18 @@ class K8sFedoraTemplateDefinition(k8s_template_def.K8sTemplateDefinition): if label_value: extra_params[label] = label_value + # NOTE(flwang): We're generating a signed cert and private key + # based on the cluster CA as the service account signing keys for + # k8s cluster, though a general public/private keypair works as well. + csr_key = x509.generate_csr_and_key(u"Kubernetes Service Account") + signed_cert = cert_manager.sign_node_certificate(cluster, + csr_key["csr"], + context=context) + extra_params['kube_service_account_key'] = \ + signed_cert.replace("\n", "\\n") + extra_params['kube_service_account_private_key'] = \ + csr_key["key"].replace("\n", "\\n") + cert_manager_api = cluster.labels.get('cert_manager_api') if strutils.bool_from_string(cert_manager_api): extra_params['cert_manager_api'] = cert_manager_api diff --git a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml index 80269cc0ab..ec97256f72 100644 --- a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml +++ b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubecluster.yaml @@ -475,6 +475,18 @@ parameters: whether or not to use Octavia for LoadBalancer type service. default: False + kube_service_account_key: + type: string + description: > + The signed cert will be used to verify the k8s service account tokens + during authentication. + + kube_service_account_private_key: + type: string + description: > + The private key will be used to sign generated k8s service account + tokens. + resources: ###################################################################### @@ -695,6 +707,9 @@ resources: kubecontroller_options: {get_param: kubecontroller_options} kubescheduler_options: {get_param: kubescheduler_options} octavia_enabled: {get_param: octavia_enabled} + kube_service_account_key: {get_param: kube_service_account_key} + kube_service_account_private_key: {get_param: kube_service_account_private_key} + ###################################################################### # diff --git a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml index df52c98232..b855931733 100644 --- a/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml +++ b/magnum/drivers/k8s_fedora_atomic_v1/templates/kubemaster.yaml @@ -369,6 +369,18 @@ parameters: the index of master node, index 0 means the master node is the primary, bootstrapping node. + kube_service_account_key: + type: string + description: > + The signed cert will be used to verify the k8s service account tokens + during authentication. + + kube_service_account_private_key: + type: string + description: > + The private key will be used to sign generated k8s service account + tokens. + resources: master_wait_handle: @@ -475,6 +487,8 @@ resources: "$KUBEPROXY_OPTIONS": {get_param: kubeproxy_options} "$KUBESCHEDULER_OPTIONS": {get_param: kubescheduler_options} "$OCTAVIA_ENABLED": {get_param: octavia_enabled} + "$KUBE_SERVICE_ACCOUNT_KEY": {get_param: kube_service_account_key} + "$KUBE_SERVICE_ACCOUNT_PRIVATE_KEY": {get_param: kube_service_account_private_key} install_openstack_ca: type: OS::Heat::SoftwareConfig diff --git a/magnum/tests/unit/common/x509/test_operations.py b/magnum/tests/unit/common/x509/test_operations.py index b6e1ce0e77..eec60a3175 100644 --- a/magnum/tests/unit/common/x509/test_operations.py +++ b/magnum/tests/unit/common/x509/test_operations.py @@ -12,6 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. +from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives import serialization import mock @@ -43,3 +44,11 @@ class TestX509Operations(base.BaseTestCase): encryption_algorithm=mock_no_encryption_class.return_value ) self.assertEqual(mock.sentinel.decrypted, actual_decrypted) + + @mock.patch.object(operations, 'default_backend') + @mock.patch.object(rsa, 'generate_private_key') + def test_generate_csr_and_key(self, mock_generate_private_key, + mock_default_backend): + mock_generate_private_key.return_value = mock.MagicMock() + csr_key = operations.generate_csr_and_key(u"Test") + self.assertIsNotNone(csr_key) diff --git a/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py b/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py index a793c0907e..38affc9b7e 100644 --- a/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_k8s_cluster_conductor.py @@ -135,16 +135,24 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): self._test_extract_template_definition( + mock_generate_csr_and_key, mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get) def _test_extract_template_definition( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -155,6 +163,9 @@ class TestClusterConductorWithK8s(base.TestCase): self.cluster_dict[missing_attr] = None cluster_template = objects.ClusterTemplate( self.context, **self.cluster_template_dict) + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'key': 'private_key'} + mock_sign_node_certificate.return_value = 'signed_cert' mock_objects_cluster_template_get_by_uuid.return_value = \ cluster_template expected_result = str('{"action":"get","node":{"key":"test","value":' @@ -272,6 +283,8 @@ class TestClusterConductorWithK8s(base.TestCase): 'kubescheduler_options': '--kubescheduler', 'kubeproxy_options': '--kubeproxy', 'octavia_enabled': False, + 'kube_service_account_key': 'signed_cert', + 'kube_service_account_private_key': 'private_key', } if missing_attr is not None: expected.pop(mapping[missing_attr], None) @@ -289,14 +302,22 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_with_registry( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): self.cluster_template_dict['registry_enabled'] = True cluster_template = objects.ClusterTemplate( self.context, **self.cluster_template_dict) + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'key': 'private_key'} + mock_sign_node_certificate.return_value = 'signed_cert' mock_objects_cluster_template_get_by_uuid.return_value = \ cluster_template expected_result = str('{"action":"get","node":{"key":"test","value":' @@ -380,6 +401,8 @@ class TestClusterConductorWithK8s(base.TestCase): 'kubescheduler_options': '--kubescheduler', 'kubeproxy_options': '--kubeproxy', 'octavia_enabled': False, + 'kube_service_account_key': 'signed_cert', + 'kube_service_account_private_key': 'private_key', } self.assertEqual(expected, definition) @@ -395,8 +418,13 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_only_required( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): @@ -412,6 +440,9 @@ class TestClusterConductorWithK8s(base.TestCase): cluster_template = objects.ClusterTemplate( self.context, **self.cluster_template_dict) + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'key': 'private_key'} + mock_sign_node_certificate.return_value = 'signed_cert' mock_objects_cluster_template_get_by_uuid.return_value = \ cluster_template expected_result = str('{"action":"get","node":{"key":"test","value":' @@ -475,6 +506,8 @@ class TestClusterConductorWithK8s(base.TestCase): 'kubescheduler_options': '--kubescheduler', 'kubeproxy_options': '--kubeproxy', 'octavia_enabled': False, + 'kube_service_account_key': 'signed_cert', + 'kube_service_account_private_key': 'private_key', } self.assertEqual(expected, definition) self.assertEqual( @@ -659,13 +692,20 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_dns( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): mock_driver.return_value = k8s_dr.Driver() self._test_extract_template_definition( + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -674,13 +714,20 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_server_image( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): mock_driver.return_value = k8s_dr.Driver() self._test_extract_template_definition( + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -689,13 +736,20 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_docker_storage_driver( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): mock_driver.return_value = k8s_dr.Driver() self._test_extract_template_definition( + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -704,13 +758,20 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_apiserver_port( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): mock_driver.return_value = k8s_dr.Driver() self._test_extract_template_definition( + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -719,13 +780,20 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_node_count( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): mock_driver.return_value = k8s_dr.Driver() self._test_extract_template_definition( + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -734,13 +802,20 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_master_count( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get): mock_driver.return_value = k8s_dr.Driver() self._test_extract_template_definition( + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, mock_get, @@ -749,13 +824,21 @@ class TestClusterConductorWithK8s(base.TestCase): @patch('requests.get') @patch('magnum.objects.ClusterTemplate.get_by_uuid') @patch('magnum.drivers.common.driver.Driver.get_driver') + @patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @patch('magnum.common.x509.operations.generate_csr_and_key') def test_extract_template_definition_without_discovery_url( self, + mock_generate_csr_and_key, + mock_sign_node_certificate, mock_driver, mock_objects_cluster_template_get_by_uuid, reqget): cluster_template = objects.ClusterTemplate( self.context, **self.cluster_template_dict) + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'key': 'private_key'} + mock_sign_node_certificate.return_value = 'signed_cert' mock_objects_cluster_template_get_by_uuid.return_value = \ cluster_template cluster_dict = self.cluster_dict @@ -833,6 +916,8 @@ class TestClusterConductorWithK8s(base.TestCase): 'kubescheduler_options': '--kubescheduler', 'kubeproxy_options': '--kubeproxy', 'octavia_enabled': False, + 'kube_service_account_key': 'signed_cert', + 'kube_service_account_private_key': 'private_key', } self.assertEqual(expected, definition) self.assertEqual( diff --git a/magnum/tests/unit/drivers/test_template_definition.py b/magnum/tests/unit/drivers/test_template_definition.py index 594362abd9..7d0d7335ac 100644 --- a/magnum/tests/unit/drivers/test_template_definition.py +++ b/magnum/tests/unit/drivers/test_template_definition.py @@ -263,9 +263,17 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase): '.get_params') @mock.patch('magnum.drivers.heat.template_def.TemplateDefinition' '.get_output') - def test_k8s_get_params(self, mock_get_output, mock_get_params, + @mock.patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @mock.patch('magnum.common.x509.operations.generate_csr_and_key') + def test_k8s_get_params(self, mock_generate_csr_and_key, + mock_sign_node_certificate, + mock_get_output, mock_get_params, mock_get_discovery_url, mock_osc_class, mock_enable_octavia): + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'key': 'private_key'} + mock_sign_node_certificate.return_value = 'signed_cert' mock_enable_octavia.return_value = False mock_context = mock.MagicMock() mock_context.auth_token = 'AUTH_TOKEN' @@ -393,6 +401,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase): 'ingress_controller': ingress_controller, 'ingress_controller_role': ingress_controller_role, 'octavia_enabled': False, + 'kube_service_account_key': 'signed_cert', + 'kube_service_account_private_key': 'private_key', }} mock_get_params.assert_called_once_with(mock_context, mock_cluster_template, @@ -407,9 +417,17 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase): '.get_params') @mock.patch('magnum.drivers.heat.template_def.TemplateDefinition' '.get_output') - def test_k8s_get_params_insecure(self, mock_get_output, mock_get_params, + @mock.patch('magnum.conductor.handlers.common.cert_manager' + '.sign_node_certificate') + @mock.patch('magnum.common.x509.operations.generate_csr_and_key') + def test_k8s_get_params_insecure(self, mock_generate_csr_and_key, + mock_sign_node_certificate, + mock_get_output, mock_get_params, mock_get_discovery_url, mock_osc_class, mock_enable_octavia): + mock_generate_csr_and_key.return_value = {'csr': 'csr', + 'key': 'private_key'} + mock_sign_node_certificate.return_value = 'signed_cert' mock_enable_octavia.return_value = False mock_context = mock.MagicMock() mock_context.auth_token = 'AUTH_TOKEN' @@ -539,6 +557,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseTemplateDefinitionTestCase): 'ingress_controller': ingress_controller, 'ingress_controller_role': ingress_controller_role, 'octavia_enabled': False, + 'kube_service_account_key': 'signed_cert', + 'kube_service_account_private_key': 'private_key', }} mock_get_params.assert_called_once_with(mock_context, mock_cluster_template, diff --git a/releasenotes/notes/sync-service-account-keys-for-multi-masters-71217c4cf4dd472c.yaml b/releasenotes/notes/sync-service-account-keys-for-multi-masters-71217c4cf4dd472c.yaml new file mode 100644 index 0000000000..f3097662ad --- /dev/null +++ b/releasenotes/notes/sync-service-account-keys-for-multi-masters-71217c4cf4dd472c.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Multi master deployments for k8s driver use different service account + keys for each api/controller manager server which leads to 401 errors + for service accounts. This patch will create a signed cert and private key + for k8s service account keys explicitly, dedicatedly for the k8s + cluster to avoid the inconsistent keys issue. +