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:
parent
0bf72ba164
commit
b9918386b0
|
@ -87,14 +87,12 @@ def _build_ca_extentions():
|
||||||
key_usage = x509.KeyUsage(False, False, False, False, False, True, False,
|
key_usage = x509.KeyUsage(False, False, False, False, False, True, False,
|
||||||
False, False)
|
False, False)
|
||||||
key_usage = x509.Extension(key_usage.oid, True, key_usage)
|
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.BasicConstraints(ca=True, path_length=0)
|
||||||
basic_constraints = x509.Extension(basic_constraints.oid, True,
|
basic_constraints = x509.Extension(basic_constraints.oid, True,
|
||||||
basic_constraints)
|
basic_constraints)
|
||||||
|
|
||||||
return [basic_constraints, key_usage, extended_key_usage]
|
return [basic_constraints, key_usage]
|
||||||
|
|
||||||
|
|
||||||
def _generate_self_signed_certificate(subject_name, extensions,
|
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):
|
def generate_csr_and_key(common_name):
|
||||||
"""Return a dict with a new csr and key."""
|
"""Return a dict with a new csr, public key and private key."""
|
||||||
key = rsa.generate_private_key(
|
private_key = rsa.generate_private_key(
|
||||||
public_exponent=65537,
|
public_exponent=65537,
|
||||||
key_size=2048,
|
key_size=2048,
|
||||||
backend=default_backend())
|
backend=default_backend())
|
||||||
|
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
|
||||||
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
|
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
|
||||||
x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, common_name),
|
x509.NameAttribute(x509.oid.NameOID.COMMON_NAME, common_name),
|
||||||
])).sign(key, hashes.SHA256(), default_backend())
|
])).sign(private_key, hashes.SHA256(), default_backend())
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
'csr': csr.public_bytes(
|
'csr': csr.public_bytes(
|
||||||
encoding=serialization.Encoding.PEM).decode("utf-8"),
|
encoding=serialization.Encoding.PEM).decode("utf-8"),
|
||||||
'key': key.private_bytes(
|
'private_key': private_key.private_bytes(
|
||||||
encoding=serialization.Encoding.PEM,
|
encoding=serialization.Encoding.PEM,
|
||||||
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
format=serialization.PrivateFormat.TraditionalOpenSSL,
|
||||||
encryption_algorithm=serialization.NoEncryption()).decode("utf-8"),
|
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
|
return result
|
||||||
|
|
|
@ -116,17 +116,12 @@ class K8sFedoraTemplateDefinition(k8s_template_def.K8sTemplateDefinition):
|
||||||
if label_value:
|
if label_value:
|
||||||
extra_params[label] = label_value
|
extra_params[label] = label_value
|
||||||
|
|
||||||
# NOTE(flwang): We're generating a signed cert and private key
|
csr_keys = x509.generate_csr_and_key(u"Kubernetes Service Account")
|
||||||
# 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'] = \
|
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'] = \
|
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')
|
cert_manager_api = cluster.labels.get('cert_manager_api')
|
||||||
if strutils.bool_from_string(cert_manager_api):
|
if strutils.bool_from_string(cert_manager_api):
|
||||||
|
|
|
@ -50,5 +50,7 @@ class TestX509Operations(base.BaseTestCase):
|
||||||
def test_generate_csr_and_key(self, mock_generate_private_key,
|
def test_generate_csr_and_key(self, mock_generate_private_key,
|
||||||
mock_default_backend):
|
mock_default_backend):
|
||||||
mock_generate_private_key.return_value = mock.MagicMock()
|
mock_generate_private_key.return_value = mock.MagicMock()
|
||||||
csr_key = operations.generate_csr_and_key(u"Test")
|
csr_keys = operations.generate_csr_and_key(u"Test")
|
||||||
self.assertIsNotNone(csr_key)
|
self.assertIsNotNone(csr_keys)
|
||||||
|
self.assertTrue("public_key" in csr_keys)
|
||||||
|
self.assertTrue("private_key" in csr_keys)
|
||||||
|
|
|
@ -164,7 +164,8 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
cluster_template = objects.ClusterTemplate(
|
cluster_template = objects.ClusterTemplate(
|
||||||
self.context, **self.cluster_template_dict)
|
self.context, **self.cluster_template_dict)
|
||||||
mock_generate_csr_and_key.return_value = {'csr': 'csr',
|
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_sign_node_certificate.return_value = 'signed_cert'
|
||||||
mock_objects_cluster_template_get_by_uuid.return_value = \
|
mock_objects_cluster_template_get_by_uuid.return_value = \
|
||||||
cluster_template
|
cluster_template
|
||||||
|
@ -283,7 +284,7 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
'kubescheduler_options': '--kubescheduler',
|
'kubescheduler_options': '--kubescheduler',
|
||||||
'kubeproxy_options': '--kubeproxy',
|
'kubeproxy_options': '--kubeproxy',
|
||||||
'octavia_enabled': False,
|
'octavia_enabled': False,
|
||||||
'kube_service_account_key': 'signed_cert',
|
'kube_service_account_key': 'public_key',
|
||||||
'kube_service_account_private_key': 'private_key',
|
'kube_service_account_private_key': 'private_key',
|
||||||
}
|
}
|
||||||
if missing_attr is not None:
|
if missing_attr is not None:
|
||||||
|
@ -316,7 +317,8 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
cluster_template = objects.ClusterTemplate(
|
cluster_template = objects.ClusterTemplate(
|
||||||
self.context, **self.cluster_template_dict)
|
self.context, **self.cluster_template_dict)
|
||||||
mock_generate_csr_and_key.return_value = {'csr': 'csr',
|
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_sign_node_certificate.return_value = 'signed_cert'
|
||||||
mock_objects_cluster_template_get_by_uuid.return_value = \
|
mock_objects_cluster_template_get_by_uuid.return_value = \
|
||||||
cluster_template
|
cluster_template
|
||||||
|
@ -401,7 +403,7 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
'kubescheduler_options': '--kubescheduler',
|
'kubescheduler_options': '--kubescheduler',
|
||||||
'kubeproxy_options': '--kubeproxy',
|
'kubeproxy_options': '--kubeproxy',
|
||||||
'octavia_enabled': False,
|
'octavia_enabled': False,
|
||||||
'kube_service_account_key': 'signed_cert',
|
'kube_service_account_key': 'public_key',
|
||||||
'kube_service_account_private_key': 'private_key',
|
'kube_service_account_private_key': 'private_key',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +443,8 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
cluster_template = objects.ClusterTemplate(
|
cluster_template = objects.ClusterTemplate(
|
||||||
self.context, **self.cluster_template_dict)
|
self.context, **self.cluster_template_dict)
|
||||||
mock_generate_csr_and_key.return_value = {'csr': 'csr',
|
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_sign_node_certificate.return_value = 'signed_cert'
|
||||||
mock_objects_cluster_template_get_by_uuid.return_value = \
|
mock_objects_cluster_template_get_by_uuid.return_value = \
|
||||||
cluster_template
|
cluster_template
|
||||||
|
@ -506,7 +509,7 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
'kubescheduler_options': '--kubescheduler',
|
'kubescheduler_options': '--kubescheduler',
|
||||||
'kubeproxy_options': '--kubeproxy',
|
'kubeproxy_options': '--kubeproxy',
|
||||||
'octavia_enabled': False,
|
'octavia_enabled': False,
|
||||||
'kube_service_account_key': 'signed_cert',
|
'kube_service_account_key': 'public_key',
|
||||||
'kube_service_account_private_key': 'private_key',
|
'kube_service_account_private_key': 'private_key',
|
||||||
}
|
}
|
||||||
self.assertEqual(expected, definition)
|
self.assertEqual(expected, definition)
|
||||||
|
@ -837,7 +840,8 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
cluster_template = objects.ClusterTemplate(
|
cluster_template = objects.ClusterTemplate(
|
||||||
self.context, **self.cluster_template_dict)
|
self.context, **self.cluster_template_dict)
|
||||||
mock_generate_csr_and_key.return_value = {'csr': 'csr',
|
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_sign_node_certificate.return_value = 'signed_cert'
|
||||||
mock_objects_cluster_template_get_by_uuid.return_value = \
|
mock_objects_cluster_template_get_by_uuid.return_value = \
|
||||||
cluster_template
|
cluster_template
|
||||||
|
@ -916,7 +920,7 @@ class TestClusterConductorWithK8s(base.TestCase):
|
||||||
'kubescheduler_options': '--kubescheduler',
|
'kubescheduler_options': '--kubescheduler',
|
||||||
'kubeproxy_options': '--kubeproxy',
|
'kubeproxy_options': '--kubeproxy',
|
||||||
'octavia_enabled': False,
|
'octavia_enabled': False,
|
||||||
'kube_service_account_key': 'signed_cert',
|
'kube_service_account_key': 'public_key',
|
||||||
'kube_service_account_private_key': 'private_key',
|
'kube_service_account_private_key': 'private_key',
|
||||||
}
|
}
|
||||||
self.assertEqual(expected, definition)
|
self.assertEqual(expected, definition)
|
||||||
|
|
|
@ -285,7 +285,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
|
||||||
mock_get_discovery_url, mock_osc_class,
|
mock_get_discovery_url, mock_osc_class,
|
||||||
mock_enable_octavia):
|
mock_enable_octavia):
|
||||||
mock_generate_csr_and_key.return_value = {'csr': 'csr',
|
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_sign_node_certificate.return_value = 'signed_cert'
|
||||||
mock_enable_octavia.return_value = False
|
mock_enable_octavia.return_value = False
|
||||||
mock_context = mock.MagicMock()
|
mock_context = mock.MagicMock()
|
||||||
|
@ -417,7 +418,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
|
||||||
'ingress_controller': ingress_controller,
|
'ingress_controller': ingress_controller,
|
||||||
'ingress_controller_role': ingress_controller_role,
|
'ingress_controller_role': ingress_controller_role,
|
||||||
'octavia_enabled': False,
|
'octavia_enabled': False,
|
||||||
'kube_service_account_key': 'signed_cert',
|
'kube_service_account_key': 'public_key',
|
||||||
'kube_service_account_private_key': 'private_key',
|
'kube_service_account_private_key': 'private_key',
|
||||||
}}
|
}}
|
||||||
mock_get_params.assert_called_once_with(mock_context,
|
mock_get_params.assert_called_once_with(mock_context,
|
||||||
|
@ -454,7 +455,8 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
|
||||||
mock_get_discovery_url, mock_osc_class,
|
mock_get_discovery_url, mock_osc_class,
|
||||||
mock_enable_octavia):
|
mock_enable_octavia):
|
||||||
mock_generate_csr_and_key.return_value = {'csr': 'csr',
|
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_sign_node_certificate.return_value = 'signed_cert'
|
||||||
mock_enable_octavia.return_value = False
|
mock_enable_octavia.return_value = False
|
||||||
mock_context = mock.MagicMock()
|
mock_context = mock.MagicMock()
|
||||||
|
@ -588,7 +590,7 @@ class AtomicK8sTemplateDefinitionTestCase(BaseK8sTemplateDefinitionTestCase):
|
||||||
'ingress_controller': ingress_controller,
|
'ingress_controller': ingress_controller,
|
||||||
'ingress_controller_role': ingress_controller_role,
|
'ingress_controller_role': ingress_controller_role,
|
||||||
'octavia_enabled': False,
|
'octavia_enabled': False,
|
||||||
'kube_service_account_key': 'signed_cert',
|
'kube_service_account_key': 'public_key',
|
||||||
'kube_service_account_private_key': 'private_key',
|
'kube_service_account_private_key': 'private_key',
|
||||||
}}
|
}}
|
||||||
mock_get_params.assert_called_once_with(mock_context,
|
mock_get_params.assert_called_once_with(mock_context,
|
||||||
|
|
Loading…
Reference in New Issue