Using simple public/private key for k8s service account keys

Due to a change in Go 1.10.3[1], which k8s v1.11.1 is based on, now
magnum is failing to create a working k8s cluster with version 1.11.1.
This patch is changing removing the extention usage for server auth
for ca cert and using simple public/private keys for k8s service account
keys.

[1] https://go.googlesource.com/go/+/09fa131c99da0ef9f78c9f4f6cd955237ccc01cd

Task: 23210
Story: 2003103

Change-Id: Ieba8f55d55db2afda6888d4bc6c2caa87370d13d
This commit is contained in:
Feilong Wang 2018-07-27 12:27:30 +12:00
parent 0bf72ba164
commit b9918386b0
5 changed files with 38 additions and 31 deletions

View File

@ -87,14 +87,12 @@ 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, extended_key_usage]
return [basic_constraints, key_usage]
def _generate_self_signed_certificate(subject_name, extensions,
@ -235,23 +233,29 @@ def sign(csr, issuer_name, ca_key, ca_key_password=None,
def generate_csr_and_key(common_name):
"""Return a dict with a new csr and key."""
key = rsa.generate_private_key(
"""Return a dict with a new csr, public key and private key."""
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend())
public_key = private_key.public_key()
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, common_name),
])).sign(key, hashes.SHA256(), default_backend())
])).sign(private_key, hashes.SHA256(), default_backend())
result = {
'csr': csr.public_bytes(
encoding=serialization.Encoding.PEM).decode("utf-8"),
'key': key.private_bytes(
'private_key': private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()).decode("utf-8"),
'public_key': public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo).decode(
"utf-8"),
}
return result

View File

@ -116,17 +116,12 @@ 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)
csr_keys = x509.generate_csr_and_key(u"Kubernetes Service Account")
extra_params['kube_service_account_key'] = \
signed_cert.replace("\n", "\\n")
csr_keys["public_key"].replace("\n", "\\n")
extra_params['kube_service_account_private_key'] = \
csr_key["key"].replace("\n", "\\n")
csr_keys["private_key"].replace("\n", "\\n")
cert_manager_api = cluster.labels.get('cert_manager_api')
if strutils.bool_from_string(cert_manager_api):

View File

@ -50,5 +50,7 @@ class TestX509Operations(base.BaseTestCase):
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)
csr_keys = operations.generate_csr_and_key(u"Test")
self.assertIsNotNone(csr_keys)
self.assertTrue("public_key" in csr_keys)
self.assertTrue("private_key" in csr_keys)

View File

@ -164,7 +164,8 @@ 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'}
'private_key': 'private_key',
'public_key': 'public_key'}
mock_sign_node_certificate.return_value = 'signed_cert'
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
@ -283,7 +284,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'kubescheduler_options': '--kubescheduler',
'kubeproxy_options': '--kubeproxy',
'octavia_enabled': False,
'kube_service_account_key': 'signed_cert',
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
}
if missing_attr is not None:
@ -316,7 +317,8 @@ 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'}
'private_key': 'private_key',
'public_key': 'public_key'}
mock_sign_node_certificate.return_value = 'signed_cert'
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
@ -401,7 +403,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'kubescheduler_options': '--kubescheduler',
'kubeproxy_options': '--kubeproxy',
'octavia_enabled': False,
'kube_service_account_key': 'signed_cert',
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
}
@ -441,7 +443,8 @@ 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'}
'private_key': 'private_key',
'public_key': 'public_key'}
mock_sign_node_certificate.return_value = 'signed_cert'
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
@ -506,7 +509,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'kubescheduler_options': '--kubescheduler',
'kubeproxy_options': '--kubeproxy',
'octavia_enabled': False,
'kube_service_account_key': 'signed_cert',
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
}
self.assertEqual(expected, definition)
@ -837,7 +840,8 @@ 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'}
'private_key': 'private_key',
'public_key': 'public_key'}
mock_sign_node_certificate.return_value = 'signed_cert'
mock_objects_cluster_template_get_by_uuid.return_value = \
cluster_template
@ -916,7 +920,7 @@ class TestClusterConductorWithK8s(base.TestCase):
'kubescheduler_options': '--kubescheduler',
'kubeproxy_options': '--kubeproxy',
'octavia_enabled': False,
'kube_service_account_key': 'signed_cert',
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
}
self.assertEqual(expected, definition)

View File

@ -285,7 +285,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
mock_get_discovery_url, mock_osc_class,
mock_enable_octavia):
mock_generate_csr_and_key.return_value = {'csr': 'csr',
'key': 'private_key'}
'private_key': 'private_key',
'public_key': 'public_key'}
mock_sign_node_certificate.return_value = 'signed_cert'
mock_enable_octavia.return_value = False
mock_context = mock.MagicMock()
@ -417,7 +418,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
'ingress_controller': ingress_controller,
'ingress_controller_role': ingress_controller_role,
'octavia_enabled': False,
'kube_service_account_key': 'signed_cert',
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
}}
mock_get_params.assert_called_once_with(mock_context,
@ -454,7 +455,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
mock_get_discovery_url, mock_osc_class,
mock_enable_octavia):
mock_generate_csr_and_key.return_value = {'csr': 'csr',
'key': 'private_key'}
'private_key': 'private_key',
'public_key': 'public_key'}
mock_sign_node_certificate.return_value = 'signed_cert'
mock_enable_octavia.return_value = False
mock_context = mock.MagicMock()
@ -588,7 +590,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
'ingress_controller': ingress_controller,
'ingress_controller_role': ingress_controller_role,
'octavia_enabled': False,
'kube_service_account_key': 'signed_cert',
'kube_service_account_key': 'public_key',
'kube_service_account_private_key': 'private_key',
}}
mock_get_params.assert_called_once_with(mock_context,