Remove nova-cert

This commit removes nova-cert which has been deprecated since change
Id7a1fc943cbe6d860a50d3cc776717b55351004b. The APIs have been hard coded
to return a 410 whenever they're called now. For the API ref a new
section for obsolete apis is added to the bottom of the page and the
certificates api ref is moved there.

Implements bp remove-nova-cert

Change-Id: I2c78a0c6599b92040146cf9f0042cff8fd2509c3
This commit is contained in:
Matthew Treinish 2017-04-24 17:57:57 -04:00
parent 7e7bdb198e
commit 2bcee77e3b
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
21 changed files with 26 additions and 555 deletions

View File

@ -180,10 +180,6 @@ on compute hosts rather than servers.
This service provides authorization for compute instances consoles.
- **nova-cert**
This service handles the management of X509 certificates.
- **Services Actions**
- **enable, disable, disable-log-reason**
@ -262,11 +258,6 @@ on compute hosts rather than servers.
about migrations. For example, they can determine the source and
destination hosts, type of migration, or changes in the server's flavor.
- **Certificates**
Nova service "nova-cert" handles the management of X509 certificates which
are used to generate certificates for euca-bundle-image.
Relationship with Volume API
============================

View File

@ -54,7 +54,6 @@ the `API guide <http://developer.openstack.org/api-guide/compute/index.html>`_.
.. include:: os-server-external-events.inc
.. include:: os-cloudpipe.inc
.. include:: extensions.inc
.. include:: os-certificates.inc
.. include:: os-networks.inc
.. include:: os-volumes.inc
.. include:: images.inc
@ -71,3 +70,12 @@ the `API guide <http://developer.openstack.org/api-guide/compute/index.html>`_.
.. include:: os-security-group-rules.inc
.. include:: os-hosts.inc
.. include:: os-virtual-interfaces.inc
=============
Obsolete APIs
=============
This section contains the reference for APIs that were part of the OpenStack
Compute API in the past, but no longer exist.
.. include:: os-certificates.inc

View File

@ -10,8 +10,8 @@ Creates and shows details for a root certificate.
This API existed solely because of the need to build euca bundles
when Nova had an in tree EC2 API. It no longer interacts with any
parts of the system besides its own certificate daemon. It is
deprecated and will be removed in the near future.
parts of the system besides its own certificate daemon. It was
removed in the 16.0.0 Pike release.
Create Root Certificate
=======================

View File

@ -29,7 +29,6 @@ Reference
nova-api-os-compute
nova-api
nova-cells
nova-cert
nova-compute
nova-conductor
nova-console

View File

@ -1,47 +0,0 @@
==========
nova-cert
==========
--------------------------------
Server for the Nova Cert
--------------------------------
:Author: openstack@lists.openstack.org
:Date: 2012-09-27
:Copyright: OpenStack Foundation
:Version: 2012.1
:Manual section: 1
:Manual group: cloud computing
SYNOPSIS
========
nova-cert [options]
DESCRIPTION
===========
nova-cert is a server daemon that serves the Nova Cert service for X509 certificates. Used to generate certificates for euca-bundle-image. Only needed for EC2 API.
OPTIONS
=======
**General options**
FILES
========
* /etc/nova/nova.conf
* /etc/nova/policy.json
* /etc/nova/rootwrap.conf
* /etc/nova/rootwrap.d/
SEE ALSO
========
* `OpenStack Nova <https://docs.openstack.org/developer/nova>`__
BUGS
====
* Nova bugs are managed at Launchpad `Bugs : Nova <https://bugs.launchpad.net/nova>`__

View File

@ -14,60 +14,24 @@
import webob.exc
from nova.api.openstack import common
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
import nova.cert.rpcapi
from nova import exception
from nova.i18n import _
from nova.policies import certificates as cert_policies
ALIAS = "os-certificates"
def _translate_certificate_view(certificate, private_key=None):
return {
'data': certificate,
'private_key': private_key,
}
class CertificatesController(wsgi.Controller):
"""The x509 Certificates API controller for the OpenStack API."""
def __init__(self):
self.cert_rpcapi = nova.cert.rpcapi.CertAPI()
super(CertificatesController, self).__init__()
@extensions.expected_errors((404, 501))
@extensions.expected_errors(410)
def show(self, req, id):
"""Return certificate information."""
context = req.environ['nova.context']
context.can(cert_policies.POLICY_ROOT % 'show')
if id != 'root':
msg = _("Only root certificate can be retrieved.")
# TODO(oomichi): This seems a HTTPBadRequest case because of the
# above message. This will be changed with a microversion in the
# future.
common.raise_feature_not_supported(msg=msg)
try:
cert = self.cert_rpcapi.fetch_ca(context,
project_id=context.project_id)
except exception.CryptoCAFileNotFound as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message())
return {'certificate': _translate_certificate_view(cert)}
raise webob.exc.HTTPGone()
# NOTE(gmann): Here should be 201 instead of 200 by v2.1
# +microversions because the resource certificate has been created
# completely when returning a response.
@extensions.expected_errors(())
@extensions.expected_errors((410))
def create(self, req, body=None):
"""Create a certificate."""
context = req.environ['nova.context']
context.can(cert_policies.POLICY_ROOT % 'create')
pk, cert = self.cert_rpcapi.generate_x509_cert(context,
user_id=context.user_id, project_id=context.project_id)
return {'certificate': _translate_certificate_view(cert, pk)}
raise webob.exc.HTTPGone()
class Certificates(extensions.V21APIExtensionBase):

View File

View File

@ -1,69 +0,0 @@
# Copyright 2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Cert manager manages x509 certificates.
**Related Flags**
:cert_manager: The module name of a class derived from
:class:`manager.Manager` (default:
:class:`nova.cert.manager.Manager`).
"""
import base64
import oslo_messaging as messaging
from nova import crypto
from nova import manager
class CertManager(manager.Manager):
target = messaging.Target(version='2.0')
def __init__(self, *args, **kwargs):
super(CertManager, self).__init__(service_name='cert',
*args, **kwargs)
def init_host(self):
crypto.ensure_ca_filesystem()
def revoke_certs_by_user(self, context, user_id):
"""Revoke all user certs."""
return crypto.revoke_certs_by_user(user_id)
def revoke_certs_by_project(self, context, project_id):
"""Revoke all project certs."""
return crypto.revoke_certs_by_project(project_id)
def revoke_certs_by_user_and_project(self, context, user_id, project_id):
"""Revoke certs for user in project."""
return crypto.revoke_certs_by_user_and_project(user_id, project_id)
def generate_x509_cert(self, context, user_id, project_id):
"""Generate and sign a cert for user in project."""
return crypto.generate_x509_cert(user_id, project_id)
def fetch_ca(self, context, project_id):
"""Get root ca for a project."""
return crypto.fetch_ca(project_id)
def fetch_crl(self, context, project_id):
"""Get crl for a project."""
return crypto.fetch_crl(project_id)
def decrypt_text(self, context, project_id, text):
"""Decrypt base64 encoded text using the projects private key."""
return crypto.decrypt_text(project_id, base64.b64decode(text))

View File

@ -1,101 +0,0 @@
# Copyright 2013, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Client side of the cert manager RPC API.
"""
import oslo_messaging as messaging
import nova.conf
from nova import profiler
from nova import rpc
CONF = nova.conf.CONF
@profiler.trace_cls("rpc")
class CertAPI(object):
'''Client side of the cert rpc API.
API version history:
1.0 - Initial version.
1.1 - Added get_backdoor_port()
... Grizzly and Havana support message version 1.1. So, any changes to
existing methods in 1.x after that point should be done such that they
can handle the version_cap being set to 1.1.
2.0 - Major API rev for Icehouse
... Icehouse, Juno, Kilo, Liberty, Mitaka, Newton, and Ocata support
message version 2.0. So, any changes to existing methods in 2.x after
that point should be done such that they can handle the version_cap
being set to 2.0.
'''
VERSION_ALIASES = {
'grizzly': '1.1',
'havana': '1.1',
'icehouse': '2.0',
'juno': '2.0',
'kilo': '2.0',
'liberty': '2.0',
'mitaka': '2.0',
'newton': '2.0',
'ocata': '2.0',
}
def __init__(self):
super(CertAPI, self).__init__()
target = messaging.Target(topic='cert', version='2.0')
version_cap = self.VERSION_ALIASES.get(CONF.upgrade_levels.cert,
CONF.upgrade_levels.cert)
self.client = rpc.get_client(target, version_cap=version_cap)
def revoke_certs_by_user(self, ctxt, user_id):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'revoke_certs_by_user', user_id=user_id)
def revoke_certs_by_project(self, ctxt, project_id):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'revoke_certs_by_project',
project_id=project_id)
def revoke_certs_by_user_and_project(self, ctxt, user_id, project_id):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'revoke_certs_by_user_and_project',
user_id=user_id, project_id=project_id)
def generate_x509_cert(self, ctxt, user_id, project_id):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'generate_x509_cert',
user_id=user_id,
project_id=project_id)
def fetch_ca(self, ctxt, project_id):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'fetch_ca', project_id=project_id)
def fetch_crl(self, ctxt, project_id):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'fetch_crl', project_id=project_id)
def decrypt_text(self, ctxt, project_id, text):
cctxt = self.client.prepare()
return cctxt.call(ctxt, 'decrypt_text',
project_id=project_id,
text=text)

View File

@ -1,49 +0,0 @@
# Copyright 2012 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Starter script for Nova Cert."""
import sys
from oslo_log import log as logging
from oslo_log import versionutils
from oslo_reports import guru_meditation_report as gmr
import nova.conf
from nova import config
from nova.i18n import _LW
from nova import objects
from nova import service
from nova import utils
from nova import version
CONF = nova.conf.CONF
def main():
config.parse_args(sys.argv)
logging.setup(CONF, "nova")
utils.monkey_patch()
objects.register_all()
log = logging.getLogger(__name__)
versionutils.report_deprecated_feature(
log,
_LW('The nova-cert service is deprecated and will be removed '
'in a future release.'))
gmr.TextGuruMeditation.setup_autorun(version)
server = service.Service.create(binary='nova-cert')
service.serve(server)
service.wait()

View File

@ -24,7 +24,6 @@ from nova.policies import baremetal_nodes
from nova.policies import base
from nova.policies import cells
from nova.policies import cells_scheduler
from nova.policies import certificates
from nova.policies import cloudpipe
from nova.policies import config_drive
from nova.policies import console_auth_tokens
@ -104,7 +103,6 @@ def list_rules():
base.list_rules(),
cells.list_rules(),
cells_scheduler.list_rules(),
certificates.list_rules(),
cloudpipe.list_rules(),
config_drive.list_rules(),
console_auth_tokens.list_rules(),

View File

@ -1,47 +0,0 @@
# Copyright 2016 Cloudbase Solutions Srl
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nova.policies import base
POLICY_ROOT = 'os_compute_api:os-certificates:%s'
certificates_policies = [
base.create_rule_default(
POLICY_ROOT % 'create',
base.RULE_ADMIN_OR_OWNER,
"Create a root certificate. This API is deprecated.",
[
{
'method': 'POST',
'path': '/os-certificates'
}
]),
base.create_rule_default(
POLICY_ROOT % 'show',
base.RULE_ADMIN_OR_OWNER,
"Show details for a root certificate. This API is deprecated.",
[
{
'method': 'GET',
'path': '/os-certificates/root'
}
])
]
def list_rules():
return certificates_policies

View File

@ -55,7 +55,6 @@ SERVICE_MANAGERS = {
'nova-compute': 'nova.compute.manager.ComputeManager',
'nova-console': 'nova.console.manager.ConsoleProxyManager',
'nova-consoleauth': 'nova.consoleauth.manager.ConsoleAuthManager',
'nova-cert': 'nova.cert.manager.CertManager',
'nova-conductor': 'nova.conductor.manager.ConductorManager',
'nova-metadata': 'nova.api.manager.MetadataManager',
'nova-scheduler': 'nova.scheduler.manager.SchedulerManager',

View File

@ -1,39 +0,0 @@
# Copyright 2012 Nebula, Inc.
# Copyright 2013 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from nova.tests.functional.api_sample_tests import api_sample_base
from nova.tests.unit import fake_crypto
class CertificatesSamplesJsonTest(api_sample_base.ApiSampleTestBaseV21):
sample_dir = "os-certificates"
def setUp(self):
super(CertificatesSamplesJsonTest, self).setUp()
self.stub_out('nova.crypto.ensure_ca_filesystem',
fake_crypto.ensure_ca_filesystem)
self.stub_out('nova.crypto.fetch_ca', fake_crypto.fetch_ca)
self.stub_out('nova.crypto.generate_x509_cert',
fake_crypto.generate_x509_cert)
self.cert = self.start_service('cert')
def test_create_certificates(self):
response = self._do_post('os-certificates',
'certificate-create-req', {})
self._verify_response('certificate-create-resp', {}, response, 200)
def test_get_root_certificate(self):
response = self._do_get('os-certificates/root')
self._verify_response('certificate-get-root-resp', {}, response, 200)

View File

@ -14,16 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
from oslo_policy import policy as oslo_policy
from webob import exc
import webob.exc
from nova.api.openstack.compute import certificates \
as certificates_v21
from nova.cert import rpcapi
from nova import context
from nova import exception
from nova import policy
from nova import test
from nova.tests.unit.api.openstack import fakes
@ -41,58 +36,9 @@ class CertificatesTestV21(test.NoDBTestCase):
self.controller = self.certificates.CertificatesController()
self.req = fakes.HTTPRequest.blank('')
def test_translate_certificate_view(self):
pk, cert = 'fakepk', 'fakecert'
view = self.certificates._translate_certificate_view(cert, pk)
self.assertEqual(view['data'], cert)
self.assertEqual(view['private_key'], pk)
def test_certificates_show_root(self):
self.assertRaises(webob.exc.HTTPGone, self.controller.show,
self.req, 'root')
@mock.patch.object(rpcapi.CertAPI, 'fetch_ca', return_value='fakeroot')
def test_certificates_show_root(self, mock_fetch_ca):
res_dict = self.controller.show(self.req, 'root')
response = {'certificate': {'data': 'fakeroot', 'private_key': None}}
self.assertEqual(res_dict, response)
mock_fetch_ca.assert_called_once_with(mock.ANY, project_id='fake')
def test_certificates_show_policy_failed(self):
rules = {
self.certificate_show_extension: "!"
}
policy.set_rules(oslo_policy.Rules.from_dict(rules))
exc = self.assertRaises(exception.PolicyNotAuthorized,
self.controller.show, self.req, 'root')
self.assertIn(self.certificate_show_extension,
exc.format_message())
@mock.patch.object(rpcapi.CertAPI, 'generate_x509_cert',
return_value=('fakepk', 'fakecert'))
def test_certificates_create_certificate(self, mock_generate_x509_cert):
res_dict = self.controller.create(self.req)
response = {
'certificate': {'data': 'fakecert',
'private_key': 'fakepk'}
}
self.assertEqual(res_dict, response)
mock_generate_x509_cert.assert_called_once_with(mock.ANY,
user_id='fake_user',
project_id='fake')
def test_certificates_create_policy_failed(self):
rules = {
self.certificate_create_extension: "!"
}
policy.set_rules(oslo_policy.Rules.from_dict(rules))
exc = self.assertRaises(exception.PolicyNotAuthorized,
self.controller.create, self.req)
self.assertIn(self.certificate_create_extension,
exc.format_message())
@mock.patch.object(rpcapi.CertAPI, 'fetch_ca',
side_effect=exception.CryptoCAFileNotFound(project='fake'))
def test_non_exist_certificates_show(self, mock_fetch_ca):
self.assertRaises(
exc.HTTPNotFound,
self.controller.show,
self.req, 'root')
def test_certificates_create_certificate(self):
self.assertRaises(webob.exc.HTTPGone, self.controller.create, self.req)

View File

@ -1,81 +0,0 @@
# Copyright 2012, Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
Unit Tests for nova.cert.rpcapi
"""
import mock
from oslo_config import cfg
from nova.cert import rpcapi as cert_rpcapi
from nova import context
from nova import test
CONF = cfg.CONF
class CertRpcAPITestCase(test.NoDBTestCase):
def _test_cert_api(self, method, **kwargs):
ctxt = context.RequestContext('fake_user', 'fake_project')
rpcapi = cert_rpcapi.CertAPI()
self.assertIsNotNone(rpcapi.client)
orig_prepare = rpcapi.client.prepare
with test.nested(
mock.patch.object(rpcapi.client, 'call'),
mock.patch.object(rpcapi.client, 'prepare'),
mock.patch.object(rpcapi.client, 'can_send_version'),
) as (
rpc_mock, prepare_mock, csv_mock
):
prepare_mock.return_value = rpcapi.client
rpc_mock.return_value = 'foo'
csv_mock.side_effect = (
lambda v: orig_prepare().can_send_version())
retval = getattr(rpcapi, method)(ctxt, **kwargs)
self.assertEqual(rpc_mock.return_value, retval)
prepare_mock.assert_called_once_with()
rpc_mock.assert_called_once_with(ctxt, method, **kwargs)
def test_revoke_certs_by_user(self):
self._test_cert_api('revoke_certs_by_user', user_id='fake_user_id')
def test_revoke_certs_by_project(self):
self._test_cert_api('revoke_certs_by_project',
project_id='fake_project_id')
def test_revoke_certs_by_user_and_project(self):
self._test_cert_api('revoke_certs_by_user_and_project',
user_id='fake_user_id',
project_id='fake_project_id')
def test_generate_x509_cert(self):
self._test_cert_api('generate_x509_cert',
user_id='fake_user_id',
project_id='fake_project_id')
def test_fetch_ca(self):
self._test_cert_api('fetch_ca', project_id='fake_project_id')
def test_fetch_crl(self):
self._test_cert_api('fetch_crl', project_id='fake_project_id')
def test_decrypt_text(self):
self._test_cert_api('decrypt_text',
project_id='fake_project_id', text='blah')

View File

@ -27,8 +27,6 @@ policy_data = """
"os_compute_api:os-attach-interfaces": "",
"os_compute_api:os-baremetal-nodes": "",
"os_compute_api:os-cells": "",
"os_compute_api:os-certificates:create": "",
"os_compute_api:os-certificates:show": "",
"os_compute_api:os-cloudpipe": "",
"os_compute_api:os-config-drive": "",
"os_compute_api:os-console-output": "",

View File

@ -382,8 +382,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-attach-interfaces",
"os_compute_api:os-attach-interfaces:create",
"os_compute_api:os-attach-interfaces:delete",
"os_compute_api:os-certificates:create",
"os_compute_api:os-certificates:show",
"os_compute_api:os-consoles:create",
"os_compute_api:os-consoles:delete",
"os_compute_api:os-consoles:index",

View File

@ -50,8 +50,6 @@ class TestProfiler(test.NoDBTestCase):
'nova.api.manager.MetadataManager',
'nova.cells.manager.CellsManager',
'nova.cells.rpcapi.CellsAPI',
'nova.cert.manager.CertManager',
'nova.cert.rpcapi.CertAPI',
'nova.compute.api.API',
'nova.compute.manager.ComputeManager',
'nova.compute.rpcapi.ComputeAPI',

View File

@ -0,0 +1,5 @@
---
upgrade:
- The deprecated nova cert daemon is now removed. The /os-certificates API
endpoint that depended on this service now returns 410 whenever it is
called.