Browse Source
Client certificate authentication is disabled by default. To enable client auth, define the following in nsx.ini: nsx_use_client_auth = True nsx_client_cert_storage = nsx-db nsx_client_cert_file = <file to store certificate and private key> To enable client auth in devstack, define the following in local.conf: NSX_USE_CLIENT_CERT_AUTH=True This commit covers only DB type of cert storage. Barbican storage and imported cert will be added later. Also planned for near future: reload cert from DB if NSX connection failes due to bad cert show warning when cert nears expiration delete cert file from file system on neutron exit Change-Id: Ic70a949b740d9149d71187b02640d3071a3e0159changes/78/420178/10
17 changed files with 468 additions and 8 deletions
@ -1 +1 @@
|
||||
e816d4fe9d4f |
||||
dd9fe5a3a526 |
||||
|
@ -0,0 +1,39 @@
|
||||
# Copyright 2016 VMware, 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. |
||||
|
||||
"""NSX Adds certificate table for client certificate management |
||||
|
||||
Revision ID: dd9fe5a3a526 |
||||
Revises: e816d4fe9d4f |
||||
Create Date: 2017-01-06 12:30:01.070022 |
||||
|
||||
""" |
||||
|
||||
# revision identifiers, used by Alembic. |
||||
revision = 'dd9fe5a3a526' |
||||
down_revision = 'e816d4fe9d4f' |
||||
|
||||
from alembic import op |
||||
import sqlalchemy as sa |
||||
|
||||
|
||||
def upgrade(): |
||||
|
||||
op.create_table('nsx_certificates', |
||||
sa.Column('purpose', sa.String(length=32), nullable=False), |
||||
sa.Column('certificate', sa.String(length=9216), nullable=False), |
||||
sa.Column('private_key', sa.String(length=5120), nullable=False), |
||||
sa.Column('updated_at', sa.DateTime(), nullable=True), |
||||
sa.Column('created_at', sa.DateTime(), nullable=True), |
||||
sa.PrimaryKeyConstraint('purpose')) |
@ -0,0 +1,53 @@
|
||||
# Copyright 2016 VMware, Inc. |
||||
# 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 vmware_nsx.db import db as nsx_db |
||||
|
||||
|
||||
NSX_OPENSTACK_IDENTITY = "com.vmware.nsx.openstack" |
||||
|
||||
|
||||
class DbCertificateStorageDriver(object): |
||||
"""Storage for certificate and private key in neutron DB""" |
||||
# TODO(annak): Add private key encryption |
||||
def __init__(self, context): |
||||
self._context = context |
||||
|
||||
def store_cert(self, purpose, certificate, private_key): |
||||
nsx_db.save_certificate(self._context.session, purpose, |
||||
certificate, private_key) |
||||
|
||||
def get_cert(self, purpose): |
||||
return nsx_db.get_certificate(self._context.session, purpose) |
||||
|
||||
def delete_cert(self, purpose): |
||||
return nsx_db.delete_certificate(self._context.session, purpose) |
||||
|
||||
|
||||
class DummyCertificateStorageDriver(object): |
||||
"""Dummy driver API implementation |
||||
|
||||
Used for external certificate import scenario |
||||
(nsx_client_cert_storage == None) |
||||
""" |
||||
|
||||
def store_cert(self, purpose, certificate, private_key): |
||||
pass |
||||
|
||||
def get_cert(self, purpose): |
||||
pass |
||||
|
||||
def delete_cert(self, purpose): |
||||
pass |
@ -0,0 +1,120 @@
|
||||
# Copyright 2016 VMware, Inc. 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. |
||||
|
||||
|
||||
import logging |
||||
|
||||
from vmware_nsx._i18n import _LI |
||||
from vmware_nsx.plugins.nsx_v3 import cert_utils |
||||
from vmware_nsx.shell.admin.plugins.common import constants |
||||
from vmware_nsx.shell.admin.plugins.common import utils as admin_utils |
||||
from vmware_nsx.shell.admin.plugins.nsxv3.resources import utils |
||||
from vmware_nsx.shell import resources as shell |
||||
from vmware_nsxlib.v3 import client_cert |
||||
from vmware_nsxlib.v3 import trust_management |
||||
|
||||
from neutron.callbacks import registry |
||||
from neutron import context |
||||
from oslo_config import cfg |
||||
|
||||
LOG = logging.getLogger(__name__) |
||||
|
||||
# default certificate validity period in days (10 years) |
||||
DEFAULT_CERT_VALIDITY_PERIOD = 3650 |
||||
|
||||
|
||||
def get_certificate_manager(**kwargs): |
||||
username, password = None, None |
||||
if kwargs.get('property'): |
||||
properties = admin_utils.parse_multi_keyval_opt(kwargs['property']) |
||||
username = properties.get('user') |
||||
password = properties.get('password') |
||||
|
||||
storage_driver_type = cfg.CONF.nsx_v3.nsx_client_cert_storage.lower() |
||||
LOG.info(_LI("Certificate storage is %s"), storage_driver_type) |
||||
if storage_driver_type == 'nsx-db': |
||||
storage_driver = cert_utils.DbCertificateStorageDriver( |
||||
context.get_admin_context()) |
||||
elif storage_driver_type == 'none': |
||||
storage_driver = cert_utils.DummyCertificateStorageDriver() |
||||
# TODO(annak) - add support for barbican storage driver |
||||
|
||||
nsx_client = utils.get_nsxv3_client(username, password, True) |
||||
nsx_trust = trust_management.NsxLibTrustManagement(nsx_client, {}) |
||||
|
||||
return client_cert.ClientCertificateManager( |
||||
cert_utils.NSX_OPENSTACK_IDENTITY, |
||||
nsx_trust, |
||||
storage_driver) |
||||
|
||||
|
||||
@admin_utils.output_header |
||||
def generate_cert(resource, event, trigger, **kwargs): |
||||
"""Generate self signed client certificate and private key |
||||
""" |
||||
|
||||
cert_manager = get_certificate_manager(**kwargs) |
||||
if cert_manager.exists(): |
||||
# Need to delete cert first |
||||
cert_manager.delete() |
||||
|
||||
cert_manager.generate(subject={}, |
||||
valid_for_days=DEFAULT_CERT_VALIDITY_PERIOD) |
||||
|
||||
|
||||
@admin_utils.output_header |
||||
def delete_cert(resource, event, trigger, **kwargs): |
||||
"""Delete client certificate and private key """ |
||||
|
||||
cert_manager = get_certificate_manager(**kwargs) |
||||
if cert_manager.exists(): |
||||
cert_manager.delete() |
||||
|
||||
|
||||
@admin_utils.output_header |
||||
def show_cert(resource, event, trigger, **kwargs): |
||||
"""Show client certificate details """ |
||||
|
||||
cert_manager = get_certificate_manager(**kwargs) |
||||
if cert_manager.exists(): |
||||
cert_pem, key_pem = cert_manager.get_pem() |
||||
expires_on = cert_manager.expires_on() |
||||
expires_in_days = cert_manager.expires_in_days() |
||||
if expires_in_days > 0: |
||||
LOG.info(_LI("Client certificate is valid. " |
||||
"Expires on %(date)s (in %(days)d days)"), |
||||
{'date': expires_on, 'days': expires_in_days}) |
||||
|
||||
else: |
||||
LOG.info(_LI("Client certificate expired on %s."), expires_on) |
||||
|
||||
LOG.info(cert_pem) |
||||
# TODO(annak): show certificate details such as subject and crypto |
||||
# and add verification same certificate is registered in NSX. |
||||
# For imported certificate, fetch from NSX |
||||
else: |
||||
LOG.info(_LI("Client certificate was not registered in the system")) |
||||
|
||||
|
||||
registry.subscribe(generate_cert, |
||||
constants.CERTIFICATE, |
||||
shell.Operations.GENERATE.value) |
||||
|
||||
registry.subscribe(show_cert, |
||||
constants.CERTIFICATE, |
||||
shell.Operations.SHOW.value) |
||||
|
||||
registry.subscribe(delete_cert, |
||||
constants.CERTIFICATE, |
||||
shell.Operations.CLEAN.value) |
Loading…
Reference in new issue