diff --git a/api-ref/source/clustertemplates.inc b/api-ref/source/clustertemplates.inc index 0c33a08d28..8353caa866 100644 --- a/api-ref/source/clustertemplates.inc +++ b/api-ref/source/clustertemplates.inc @@ -47,6 +47,7 @@ Request - image_id: image_id - volume_driver: volume_driver - registry_enabled: registry_enabled + - insecure_registry: insecure_registry - docker_storage_driver: docker_storage_driver - name: name - network_driver: network_driver diff --git a/api-ref/source/samples/clustertemplate-create-req.json b/api-ref/source/samples/clustertemplate-create-req.json index 38bb40c584..4e1f4f5b7a 100644 --- a/api-ref/source/samples/clustertemplate-create-req.json +++ b/api-ref/source/samples/clustertemplate-create-req.json @@ -16,6 +16,7 @@ "image_id":"fedora-atomic-latest", "volume_driver":"cinder", "registry_enabled":false, + "insecure_registry":null, "docker_storage_driver":"devicemapper", "name":"k8s-bm2", "network_driver":"flannel", diff --git a/magnum/common/x509/operations.py b/magnum/common/x509/operations.py index 7d8c5a8ebe..8e2c59a5f8 100644 --- a/magnum/common/x509/operations.py +++ b/magnum/common/x509/operations.py @@ -223,6 +223,12 @@ def sign(csr, issuer_name, ca_key, ca_key_password=None, builder = builder.add_extension(extention.value, critical=extention.critical) + subject_key_identifier = x509.SubjectKeyIdentifier.from_public_key( + csr.public_key()) + builder = builder.add_extension( + subject_key_identifier, critical=False + ) + certificate = builder.sign( private_key=ca_key, algorithm=hashes.SHA256(), ).public_bytes(serialization.Encoding.PEM).strip() diff --git a/magnum/tests/unit/api/base.py b/magnum/tests/unit/api/base.py index 233556dfd4..6edd895dfa 100644 --- a/magnum/tests/unit/api/base.py +++ b/magnum/tests/unit/api/base.py @@ -67,9 +67,10 @@ def reset_pecan(): self.addCleanup(reset_pecan) - p = mock.patch('magnum.api.controllers.v1.Controller._check_version') - self._check_version = p.start() - self.addCleanup(p.stop) + # Controller._check_version is needed in some tests, + # must be mocked in others. Enable the mock when needed. + self.patch_check_version = mock.patch( + 'magnum.api.controllers.v1.Controller._check_version') def _verify_attrs(self, attrs, response, positive=True): if positive is True: diff --git a/magnum/tests/unit/api/controllers/test_root.py b/magnum/tests/unit/api/controllers/test_root.py index 4c58f426de..97adeead73 100644 --- a/magnum/tests/unit/api/controllers/test_root.py +++ b/magnum/tests/unit/api/controllers/test_root.py @@ -222,9 +222,12 @@ def test_healthcheck_disable_file(self): class TestV1Routing(api_base.FunctionalTest): def test_route_checks_version(self): + # Temporarily instantiate mock for Controller._check_version + self._check_version = self.patch_check_version.start() self.get_json('/') self._check_version.assert_called_once_with(mock.ANY, mock.ANY) + self.patch_check_version.stop() class TestCheckVersions(test_base.TestCase): diff --git a/magnum/tests/unit/api/controllers/v1/test_nodegroup.py b/magnum/tests/unit/api/controllers/v1/test_nodegroup.py index 5e61bc16a6..a2b757c974 100644 --- a/magnum/tests/unit/api/controllers/v1/test_nodegroup.py +++ b/magnum/tests/unit/api/controllers/v1/test_nodegroup.py @@ -253,6 +253,24 @@ def test_get_all_wrong_microversion(self): response = self.get_json(url, headers=headers, expect_errors=True) self.assertEqual(406, response.status_code) + def test_get_all_api_minor_version_above_range(self): + headers = {"Openstack-Api-Version": "container-infra 1.999"} + url = '/clusters/%s/nodegroups/' % (self.cluster.uuid) + response = self.get_json(url, headers=headers, expect_errors=True) + self.assertEqual(406, response.status_code) + self.assertIsNotNone(response.json['errors']) + self.assertEqual('magnum.microversion-unsupported', + response.json['errors'][0]['code']) + + def test_get_all_api_major_version_above_range(self): + headers = {"Openstack-Api-Version": "container-infra 2.11"} + url = '/clusters/%s/nodegroups/' % (self.cluster.uuid) + response = self.get_json(url, headers=headers, expect_errors=True) + self.assertEqual(406, response.status_code) + self.assertIsNotNone(response.json['errors']) + self.assertEqual('magnum.microversion-unsupported', + response.json['errors'][0]['code']) + class TestPost(NodeGroupControllerTest): def setUp(self): diff --git a/magnum/tests/unit/common/x509/test_sign.py b/magnum/tests/unit/common/x509/test_sign.py index 42083ebfe0..e52a513bf7 100644 --- a/magnum/tests/unit/common/x509/test_sign.py +++ b/magnum/tests/unit/common/x509/test_sign.py @@ -233,6 +233,26 @@ def test_sign_empty_chars(self, mock_load_pem): self.assertEqual(certificate, certificate.strip()) + # If a subject key identifier is given in the CSR, ensure it is added + @mock.patch('cryptography.x509.load_pem_x509_csr') + def test_sign_subject_key_identifier(self, mock_load_pem): + ca_key = self._generate_private_key() + private_key = self._generate_private_key() + csr_obj = self._build_csr(private_key) + csr = csr_obj.public_bytes(serialization.Encoding.PEM) + csr = csr.decode('utf-8') + + mock_load_pem.return_value = csr_obj + certificate = operations.sign(csr, self.issuer_name, + ca_key, skip_validation=True) + + # Ensure the Subject Key Identifier extension is present + cert = c_x509.load_pem_x509_certificate(certificate) + ext_ski = [ext for ext in cert.extensions + if cert.extensions[0].oid == + c_x509.oid.ExtensionOID.SUBJECT_KEY_IDENTIFIER] + self.assertEqual(len(ext_ski), 1) + def test_sign_with_invalid_csr(self): ca_key = self._generate_private_key() csr = 'test' diff --git a/releasenotes/notes/add-subject-key-identifer-ae5c6ebe86749239.yaml b/releasenotes/notes/add-subject-key-identifer-ae5c6ebe86749239.yaml new file mode 100644 index 0000000000..570aa7423a --- /dev/null +++ b/releasenotes/notes/add-subject-key-identifer-ae5c6ebe86749239.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Add subject key identifier extension to x509 operations + signing function. Allows for magnum Kubernetes clusters + to generate certificates with authority key + identifier extension.