[NetApp] Recreate security cert during vserver create.
The certificate is automatically created on NetApp with 1 year i.e. 365 days of expiration time, and admin needs to manually extend it. It would be nice Manila can take care to create certs with admin configuable expiration time. Manila should first create the new cert with given expiration time and if successful, delete the old cert. Closes-bug: #2011693 Change-Id: I37e52b94dc492e91fe9e673b3619e6716737d39a
This commit is contained in:
parent
afd0d723bb
commit
0553eb78be
@ -175,7 +175,8 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
||||||
root_volume_name, aggregate_names, ipspace_name):
|
root_volume_name, aggregate_names, ipspace_name,
|
||||||
|
security_cert_expire_days):
|
||||||
"""Creates new vserver and assigns aggregates."""
|
"""Creates new vserver and assigns aggregates."""
|
||||||
self._create_vserver(
|
self._create_vserver(
|
||||||
vserver_name, aggregate_names, ipspace_name,
|
vserver_name, aggregate_names, ipspace_name,
|
||||||
@ -183,6 +184,7 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||||||
root_volume_aggregate_name=root_volume_aggregate_name,
|
root_volume_aggregate_name=root_volume_aggregate_name,
|
||||||
root_volume_security_style='unix',
|
root_volume_security_style='unix',
|
||||||
name_server_switch='file')
|
name_server_switch='file')
|
||||||
|
self._modify_security_cert(vserver_name, security_cert_expire_days)
|
||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def create_vserver_dp_destination(self, vserver_name, aggregate_names,
|
def create_vserver_dp_destination(self, vserver_name, aggregate_names,
|
||||||
@ -230,6 +232,119 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
|
|||||||
}
|
}
|
||||||
self.send_request('vserver-modify', modify_args)
|
self.send_request('vserver-modify', modify_args)
|
||||||
|
|
||||||
|
@na_utils.trace
|
||||||
|
def _modify_security_cert(self, vserver_name, security_cert_expire_days):
|
||||||
|
"""Create new security certificate with given expire days."""
|
||||||
|
|
||||||
|
# Do not modify security certificate if specified expire days are
|
||||||
|
# equal to default security certificate expire days i.e. 365.
|
||||||
|
if security_cert_expire_days == 365:
|
||||||
|
return
|
||||||
|
|
||||||
|
api_args = {
|
||||||
|
'query': {
|
||||||
|
'certificate-info': {
|
||||||
|
'vserver': vserver_name,
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'certificate-authority': vserver_name,
|
||||||
|
'type': 'server',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'desired-attributes': {
|
||||||
|
'certificate-info': {
|
||||||
|
'serial-number': None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
result = self.send_iter_request('security-certificate-get-iter',
|
||||||
|
api_args)
|
||||||
|
try:
|
||||||
|
old_certificate_info_list = result.get_child_by_name(
|
||||||
|
'attributes-list')
|
||||||
|
except AttributeError:
|
||||||
|
LOG.warning('Could not retrieve certificate-info for vserver '
|
||||||
|
'%(server)s.', {'server': vserver_name})
|
||||||
|
return
|
||||||
|
|
||||||
|
old_serial_nums = []
|
||||||
|
for certificate_info in old_certificate_info_list.get_children():
|
||||||
|
serial_num = certificate_info.get_child_content('serial-number')
|
||||||
|
old_serial_nums.append(serial_num)
|
||||||
|
|
||||||
|
try:
|
||||||
|
create_args = {
|
||||||
|
'vserver': vserver_name,
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'type': 'server',
|
||||||
|
'expire-days': security_cert_expire_days,
|
||||||
|
}
|
||||||
|
self.send_request('security-certificate-create', create_args)
|
||||||
|
except netapp_api.NaApiError as e:
|
||||||
|
LOG.warning("Failed to create new security certificate: %s - %s",
|
||||||
|
e.code, e.message)
|
||||||
|
return
|
||||||
|
|
||||||
|
api_args = {
|
||||||
|
'query': {
|
||||||
|
'certificate-info': {
|
||||||
|
'vserver': vserver_name,
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'certificate-authority': vserver_name,
|
||||||
|
'type': 'server',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'desired-attributes': {
|
||||||
|
'certificate-info': {
|
||||||
|
'serial-number': None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
result = self.send_iter_request('security-certificate-get-iter',
|
||||||
|
api_args)
|
||||||
|
try:
|
||||||
|
new_certificate_info_list = result.get_child_by_name(
|
||||||
|
'attributes-list')
|
||||||
|
except AttributeError:
|
||||||
|
LOG.warning('Could not retrieve certificate-info for vserver '
|
||||||
|
'%(server)s.', {'server': vserver_name})
|
||||||
|
return
|
||||||
|
|
||||||
|
for certificate_info in new_certificate_info_list.get_children():
|
||||||
|
serial_num = certificate_info.get_child_content('serial-number')
|
||||||
|
if serial_num not in old_serial_nums:
|
||||||
|
try:
|
||||||
|
ssl_modify_args = {
|
||||||
|
'certificate-authority': vserver_name,
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'certificate-serial-number': serial_num,
|
||||||
|
'vserver': vserver_name,
|
||||||
|
'client-authentication-enabled': 'false',
|
||||||
|
'server-authentication-enabled': 'true',
|
||||||
|
}
|
||||||
|
self.send_request('security-ssl-modify', ssl_modify_args)
|
||||||
|
except netapp_api.NaApiError as e:
|
||||||
|
LOG.debug('Failed to modify SSL for security certificate '
|
||||||
|
'with serial number %s: %s - %s', serial_num,
|
||||||
|
e.code, e.message)
|
||||||
|
|
||||||
|
# Delete all old security certificates
|
||||||
|
for certificate_info in old_certificate_info_list.get_children():
|
||||||
|
serial_num = certificate_info.get_child_content('serial-number')
|
||||||
|
delete_args = {
|
||||||
|
'certificate-authority': vserver_name,
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'serial-number': serial_num,
|
||||||
|
'type': 'server',
|
||||||
|
'vserver': vserver_name,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
self.send_request('security-certificate-delete', delete_args)
|
||||||
|
except netapp_api.NaApiError as e:
|
||||||
|
LOG.warning('Failed to delete security certificate with '
|
||||||
|
'serial number %s: %s - %s', serial_num, e.code,
|
||||||
|
e.message)
|
||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def get_vserver_info(self, vserver_name):
|
def get_vserver_info(self, vserver_name):
|
||||||
"""Retrieves Vserver info."""
|
"""Retrieves Vserver info."""
|
||||||
|
@ -46,6 +46,7 @@ CUTOVER_ACTION_MAP = {
|
|||||||
DEFAULT_TIMEOUT = 15
|
DEFAULT_TIMEOUT = 15
|
||||||
DEFAULT_TCP_MAX_XFER_SIZE = 65536
|
DEFAULT_TCP_MAX_XFER_SIZE = 65536
|
||||||
DEFAULT_UDP_MAX_XFER_SIZE = 32768
|
DEFAULT_UDP_MAX_XFER_SIZE = 32768
|
||||||
|
DEFAULT_SECURITY_CERT_EXPIRE_DAYS = 365
|
||||||
|
|
||||||
|
|
||||||
class NetAppRestClient(object):
|
class NetAppRestClient(object):
|
||||||
@ -4120,7 +4121,8 @@ class NetAppRestClient(object):
|
|||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
def create_vserver(self, vserver_name, root_volume_aggregate_name,
|
||||||
root_volume_name, aggregate_names, ipspace_name):
|
root_volume_name, aggregate_names, ipspace_name,
|
||||||
|
security_cert_expire_days):
|
||||||
"""Creates new vserver and assigns aggregates."""
|
"""Creates new vserver and assigns aggregates."""
|
||||||
|
|
||||||
# NOTE(nahimsouza): root_volume_aggregate_name and root_volume_name
|
# NOTE(nahimsouza): root_volume_aggregate_name and root_volume_name
|
||||||
@ -4129,6 +4131,7 @@ class NetAppRestClient(object):
|
|||||||
self._create_vserver(
|
self._create_vserver(
|
||||||
vserver_name, aggregate_names, ipspace_name,
|
vserver_name, aggregate_names, ipspace_name,
|
||||||
name_server_switch=['files'])
|
name_server_switch=['files'])
|
||||||
|
self._modify_security_cert(vserver_name, security_cert_expire_days)
|
||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def create_vserver_dp_destination(self, vserver_name, aggregate_names,
|
def create_vserver_dp_destination(self, vserver_name, aggregate_names,
|
||||||
@ -4161,6 +4164,77 @@ class NetAppRestClient(object):
|
|||||||
|
|
||||||
self.send_request('/svm/svms', 'post', body=body)
|
self.send_request('/svm/svms', 'post', body=body)
|
||||||
|
|
||||||
|
@na_utils.trace
|
||||||
|
def _modify_security_cert(self, vserver_name, security_cert_expire_days):
|
||||||
|
"""Create new security certificate with given expire days."""
|
||||||
|
|
||||||
|
# Do not modify security certificate if specified expire days are
|
||||||
|
# equal to default security certificate expire days i.e. 365.
|
||||||
|
if security_cert_expire_days == DEFAULT_SECURITY_CERT_EXPIRE_DAYS:
|
||||||
|
return
|
||||||
|
|
||||||
|
query = {
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'ca': vserver_name,
|
||||||
|
'type': 'server',
|
||||||
|
'svm.name': vserver_name,
|
||||||
|
}
|
||||||
|
result = self.send_request('/security/certificates',
|
||||||
|
'get', query=query)
|
||||||
|
old_certificate_info_list = result.get('records', [])
|
||||||
|
if not old_certificate_info_list:
|
||||||
|
LOG.warning("Unable to retrieve certificate-info for vserver "
|
||||||
|
"%(server)s'. Cannot set the certificate expiry to "
|
||||||
|
"%s(conf)s. ", {'server': vserver_name,
|
||||||
|
'conf': security_cert_expire_days})
|
||||||
|
return
|
||||||
|
|
||||||
|
body = {
|
||||||
|
'common-name': vserver_name,
|
||||||
|
'type': 'server',
|
||||||
|
'svm.name': vserver_name,
|
||||||
|
'expiry_time': f'P{security_cert_expire_days}DT',
|
||||||
|
}
|
||||||
|
query = {
|
||||||
|
'return_records': 'true'
|
||||||
|
}
|
||||||
|
result = self.send_request('/security/certificates',
|
||||||
|
'post', body=body, query=query)
|
||||||
|
new_certificate_info_list = result.get('records', [])
|
||||||
|
if not new_certificate_info_list:
|
||||||
|
LOG.warning('Failed to create new security certificate for '
|
||||||
|
'vserver %(server)s.', {'server': vserver_name})
|
||||||
|
return
|
||||||
|
|
||||||
|
for certificate_info in new_certificate_info_list:
|
||||||
|
cert_uuid = certificate_info.get('uuid', None)
|
||||||
|
svm = certificate_info.get('svm', [])
|
||||||
|
svm_uuid = svm.get('uuid', None)
|
||||||
|
if not svm_uuid or not cert_uuid:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
body = {
|
||||||
|
'certificate': {
|
||||||
|
'uuid': cert_uuid,
|
||||||
|
},
|
||||||
|
'client_enabled': 'false',
|
||||||
|
}
|
||||||
|
self.send_request(f'/svm/svms/{svm_uuid}', 'patch',
|
||||||
|
body=body)
|
||||||
|
except netapp_api.api.NaApiError:
|
||||||
|
LOG.debug('Failed to modify SSL for vserver '
|
||||||
|
'%(server)s.', {'server': vserver_name})
|
||||||
|
|
||||||
|
# Delete all old security certificates
|
||||||
|
for certificate_info in old_certificate_info_list:
|
||||||
|
uuid = certificate_info.get('uuid', None)
|
||||||
|
try:
|
||||||
|
self.send_request(f'/security/certificates/{uuid}', 'delete')
|
||||||
|
except netapp_api.api.NaApiError:
|
||||||
|
LOG.error("Failed to delete security certificate for vserver "
|
||||||
|
"%s.", vserver_name)
|
||||||
|
|
||||||
@na_utils.trace
|
@na_utils.trace
|
||||||
def list_node_data_ports(self, node):
|
def list_node_data_ports(self, node):
|
||||||
"""List data ports from node."""
|
"""List data ports from node."""
|
||||||
|
@ -343,7 +343,8 @@ class NetAppCmodeMultiSVMFileStorageLibrary(
|
|||||||
self.configuration.netapp_root_volume_aggregate,
|
self.configuration.netapp_root_volume_aggregate,
|
||||||
self.configuration.netapp_root_volume,
|
self.configuration.netapp_root_volume,
|
||||||
aggr_set,
|
aggr_set,
|
||||||
ipspace_name)
|
ipspace_name,
|
||||||
|
self.configuration.netapp_security_cert_expire_days)
|
||||||
|
|
||||||
vserver_client = self._get_api_client(vserver=vserver_name)
|
vserver_client = self._get_api_client(vserver=vserver_name)
|
||||||
|
|
||||||
|
@ -190,6 +190,14 @@ netapp_provisioning_opts = [
|
|||||||
default=60, # Default to one minutes
|
default=60, # Default to one minutes
|
||||||
help='Sets maximum amount of time in seconds to wait for a '
|
help='Sets maximum amount of time in seconds to wait for a '
|
||||||
'synchronous ONTAP REST API operation to be completed.'),
|
'synchronous ONTAP REST API operation to be completed.'),
|
||||||
|
cfg.IntOpt('netapp_security_cert_expire_days',
|
||||||
|
min=1,
|
||||||
|
max=3652,
|
||||||
|
default=365,
|
||||||
|
help='Defines the expiration time (in days) for the '
|
||||||
|
'certificate created during the vserver creation. This '
|
||||||
|
'option only applies when the option '
|
||||||
|
'driver_handles_share_servers is set to True.'),
|
||||||
]
|
]
|
||||||
|
|
||||||
netapp_cluster_opts = [
|
netapp_cluster_opts = [
|
||||||
|
@ -50,6 +50,8 @@ VSERVER_PEER_STATE = 'peered'
|
|||||||
ADMIN_VSERVER_NAME = 'fake_admin_vserver'
|
ADMIN_VSERVER_NAME = 'fake_admin_vserver'
|
||||||
NODE_VSERVER_NAME = 'fake_node_vserver'
|
NODE_VSERVER_NAME = 'fake_node_vserver'
|
||||||
NFS_VERSIONS = ['nfs3', 'nfs4.0']
|
NFS_VERSIONS = ['nfs3', 'nfs4.0']
|
||||||
|
SECURITY_CERT_DEFAULT_EXPIRE_DAYS = 365
|
||||||
|
SECURITY_CERT_LARGE_EXPIRE_DAYS = 3652
|
||||||
ROOT_AGGREGATE_NAMES = ('root_aggr1', 'root_aggr2')
|
ROOT_AGGREGATE_NAMES = ('root_aggr1', 'root_aggr2')
|
||||||
ROOT_VOLUME_AGGREGATE_NAME = 'fake_root_aggr'
|
ROOT_VOLUME_AGGREGATE_NAME = 'fake_root_aggr'
|
||||||
ROOT_VOLUME_NAME = 'fake_root_volume'
|
ROOT_VOLUME_NAME = 'fake_root_volume'
|
||||||
@ -315,6 +317,18 @@ VSERVER_GET_RESPONSE = etree.XML("""
|
|||||||
'aggr2': SHARE_AGGREGATE_NAMES[1],
|
'aggr2': SHARE_AGGREGATE_NAMES[1],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
SECURITY_CERT_GET_RESPONSE = etree.XML("""
|
||||||
|
<results status="passed">
|
||||||
|
<attributes-list>
|
||||||
|
<certificate-info>
|
||||||
|
<vserver>%(vserver)s</vserver>
|
||||||
|
<serial-number>12345</serial-number>
|
||||||
|
</certificate-info>
|
||||||
|
</attributes-list>
|
||||||
|
<num-records>1</num-records>
|
||||||
|
</results>
|
||||||
|
""" % {'vserver': VSERVER_NAME})
|
||||||
|
|
||||||
VSERVER_DATA_LIST_RESPONSE = etree.XML("""
|
VSERVER_DATA_LIST_RESPONSE = etree.XML("""
|
||||||
<results status="passed">
|
<results status="passed">
|
||||||
<attributes-list>
|
<attributes-list>
|
||||||
@ -4451,6 +4465,46 @@ SERVICE_POLICIES_REST = {
|
|||||||
'num_records': 1,
|
'num_records': 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECURITY_CERT_GET_RESPONSE_REST = {
|
||||||
|
'records': [
|
||||||
|
{
|
||||||
|
'uuid': 'fake_cert_uuid',
|
||||||
|
'serial_number': 'fake_serial_number',
|
||||||
|
'key_size': 0,
|
||||||
|
'hash_function': "sha256",
|
||||||
|
'common_name': "fake_common_name",
|
||||||
|
'name': "cert1",
|
||||||
|
'ca': 'fake_ca',
|
||||||
|
'expiry_time': 'fake_expiry_time',
|
||||||
|
'svm': {
|
||||||
|
'name': VSERVER_NAME,
|
||||||
|
'uuid': 'fake_uuid',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'num_records': 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
SECURITY_CERT_POST_RESPONSE_REST = {
|
||||||
|
'records': [
|
||||||
|
{
|
||||||
|
'uuid': 'fake_cert_uuid',
|
||||||
|
'serial_number': 'fake_serial_number',
|
||||||
|
'key_size': 0,
|
||||||
|
'hash_function': "sha256",
|
||||||
|
'common_name': "fake_common_name",
|
||||||
|
'name': "cert1",
|
||||||
|
'ca': 'fake_ca',
|
||||||
|
'expiry_time': 'fake_expiry_time',
|
||||||
|
'svm': {
|
||||||
|
'name': VSERVER_NAME,
|
||||||
|
'uuid': 'fake_uuid',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'num_records': 1,
|
||||||
|
}
|
||||||
|
|
||||||
GET_SNAPMIRROR_POLICIES_REST = {
|
GET_SNAPMIRROR_POLICIES_REST = {
|
||||||
|
|
||||||
"records": [
|
"records": [
|
||||||
|
@ -420,6 +420,9 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||||||
def test_create_vserver_no_ipspace(self):
|
def test_create_vserver_no_ipspace(self):
|
||||||
|
|
||||||
self.mock_object(self.client, 'send_request')
|
self.mock_object(self.client, 'send_request')
|
||||||
|
self.mock_object(self.client,
|
||||||
|
'_modify_security_cert',
|
||||||
|
mock.Mock())
|
||||||
|
|
||||||
vserver_create_args = {
|
vserver_create_args = {
|
||||||
'vserver-name': fake.VSERVER_NAME,
|
'vserver-name': fake.VSERVER_NAME,
|
||||||
@ -438,16 +441,22 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||||||
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||||
fake.ROOT_VOLUME_NAME,
|
fake.ROOT_VOLUME_NAME,
|
||||||
fake.SHARE_AGGREGATE_NAMES,
|
fake.SHARE_AGGREGATE_NAMES,
|
||||||
None)
|
None,
|
||||||
|
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
self.client.send_request.assert_has_calls([
|
self.client.send_request.assert_has_calls([
|
||||||
mock.call('vserver-create', vserver_create_args),
|
mock.call('vserver-create', vserver_create_args),
|
||||||
mock.call('vserver-modify', vserver_modify_args)])
|
mock.call('vserver-modify', vserver_modify_args)])
|
||||||
|
self.client._modify_security_cert.assert_called_with(
|
||||||
|
fake.VSERVER_NAME, fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
def test_create_vserver_with_ipspace(self):
|
def test_create_vserver_with_ipspace(self):
|
||||||
|
|
||||||
self.client.features.add_feature('IPSPACES')
|
self.client.features.add_feature('IPSPACES')
|
||||||
self.mock_object(self.client, 'send_request')
|
self.mock_object(self.client, 'send_request')
|
||||||
|
self.mock_object(self.client,
|
||||||
|
'_modify_security_cert',
|
||||||
|
mock.Mock())
|
||||||
|
|
||||||
vserver_create_args = {
|
vserver_create_args = {
|
||||||
'vserver-name': fake.VSERVER_NAME,
|
'vserver-name': fake.VSERVER_NAME,
|
||||||
@ -467,11 +476,65 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||||||
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||||
fake.ROOT_VOLUME_NAME,
|
fake.ROOT_VOLUME_NAME,
|
||||||
fake.SHARE_AGGREGATE_NAMES,
|
fake.SHARE_AGGREGATE_NAMES,
|
||||||
fake.IPSPACE_NAME)
|
fake.IPSPACE_NAME,
|
||||||
|
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
self.client.send_request.assert_has_calls([
|
self.client.send_request.assert_has_calls([
|
||||||
mock.call('vserver-create', vserver_create_args),
|
mock.call('vserver-create', vserver_create_args),
|
||||||
mock.call('vserver-modify', vserver_modify_args)])
|
mock.call('vserver-modify', vserver_modify_args)])
|
||||||
|
self.client._modify_security_cert.assert_called_with(
|
||||||
|
fake.VSERVER_NAME, fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
|
def test__modify_security_cert(self):
|
||||||
|
|
||||||
|
certificate_create_args = {
|
||||||
|
'vserver': fake.VSERVER_NAME,
|
||||||
|
'common-name': fake.VSERVER_NAME,
|
||||||
|
'type': 'server',
|
||||||
|
'expire-days': fake.SECURITY_CERT_LARGE_EXPIRE_DAYS,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.mock_object(self.client, 'send_request')
|
||||||
|
api_response = netapp_api.NaElement(fake.SECURITY_CERT_GET_RESPONSE)
|
||||||
|
self.mock_object(self.client,
|
||||||
|
'send_iter_request',
|
||||||
|
mock.Mock(return_value=api_response))
|
||||||
|
certificate_get_args = {
|
||||||
|
'query': {
|
||||||
|
'certificate-info': {
|
||||||
|
'vserver': fake.VSERVER_NAME,
|
||||||
|
'common-name': fake.VSERVER_NAME,
|
||||||
|
'certificate-authority': fake.VSERVER_NAME,
|
||||||
|
'type': 'server',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'desired-attributes': {
|
||||||
|
'certificate-info': {
|
||||||
|
'serial-number': None,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate_delete_args = {
|
||||||
|
'certificate-authority': fake.VSERVER_NAME,
|
||||||
|
'common-name': fake.VSERVER_NAME,
|
||||||
|
'serial-number': '12345',
|
||||||
|
'type': 'server',
|
||||||
|
'vserver': fake.VSERVER_NAME,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client._modify_security_cert(
|
||||||
|
fake.VSERVER_NAME,
|
||||||
|
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
|
self.client.send_request.assert_has_calls([
|
||||||
|
mock.call(
|
||||||
|
'security-certificate-create', certificate_create_args),
|
||||||
|
mock.call(
|
||||||
|
'security-certificate-delete', certificate_delete_args)])
|
||||||
|
|
||||||
|
self.client.send_iter_request.assert_has_calls([
|
||||||
|
mock.call('security-certificate-get-iter', certificate_get_args)])
|
||||||
|
|
||||||
def test_create_vserver_dp_destination(self):
|
def test_create_vserver_dp_destination(self):
|
||||||
|
|
||||||
@ -506,7 +569,8 @@ class NetAppClientCmodeTestCase(test.TestCase):
|
|||||||
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
fake.ROOT_VOLUME_AGGREGATE_NAME,
|
||||||
fake.ROOT_VOLUME_NAME,
|
fake.ROOT_VOLUME_NAME,
|
||||||
fake.SHARE_AGGREGATE_NAMES,
|
fake.SHARE_AGGREGATE_NAMES,
|
||||||
fake.IPSPACE_NAME)
|
fake.IPSPACE_NAME,
|
||||||
|
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
def test_get_vserver_root_volume_name(self):
|
def test_get_vserver_root_volume_name(self):
|
||||||
|
|
||||||
|
@ -4808,13 +4808,69 @@ class NetAppRestCmodeClientTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_create_vserver(self):
|
def test_create_vserver(self):
|
||||||
mock = self.mock_object(self.client, '_create_vserver')
|
mock = self.mock_object(self.client, '_create_vserver')
|
||||||
|
self.mock_object(self.client, '_modify_security_cert',
|
||||||
|
mock.Mock(return_value=[]))
|
||||||
self.client.create_vserver(fake.VSERVER_NAME, None, None,
|
self.client.create_vserver(fake.VSERVER_NAME, None, None,
|
||||||
[fake.SHARE_AGGREGATE_NAME],
|
[fake.SHARE_AGGREGATE_NAME],
|
||||||
fake.IPSPACE_NAME)
|
fake.IPSPACE_NAME,
|
||||||
|
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS)
|
||||||
mock.assert_called_once_with(fake.VSERVER_NAME,
|
mock.assert_called_once_with(fake.VSERVER_NAME,
|
||||||
[fake.SHARE_AGGREGATE_NAME],
|
[fake.SHARE_AGGREGATE_NAME],
|
||||||
fake.IPSPACE_NAME,
|
fake.IPSPACE_NAME,
|
||||||
name_server_switch=['files'])
|
name_server_switch=['files'])
|
||||||
|
self.client._modify_security_cert.assert_called_once_with(
|
||||||
|
fake.VSERVER_NAME,
|
||||||
|
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS)
|
||||||
|
|
||||||
|
def test__modify_security_cert(self):
|
||||||
|
api_response = copy.deepcopy(fake.SECURITY_CERT_GET_RESPONSE_REST)
|
||||||
|
api_response2 = copy.deepcopy(fake.SECURITY_CERT_POST_RESPONSE_REST)
|
||||||
|
self.mock_object(
|
||||||
|
self.client, 'send_request',
|
||||||
|
mock.Mock(side_effect=[api_response, api_response2, None, None]))
|
||||||
|
|
||||||
|
query = {
|
||||||
|
'common-name': fake.VSERVER_NAME,
|
||||||
|
'ca': fake.VSERVER_NAME,
|
||||||
|
'type': 'server',
|
||||||
|
'svm.name': fake.VSERVER_NAME,
|
||||||
|
}
|
||||||
|
old_cert_info = copy.deepcopy(
|
||||||
|
fake.SECURITY_CERT_GET_RESPONSE_REST['records'][0])
|
||||||
|
old_cert_uuid = old_cert_info['uuid']
|
||||||
|
|
||||||
|
body1 = {
|
||||||
|
'common-name': fake.VSERVER_NAME,
|
||||||
|
'type': 'server',
|
||||||
|
'svm.name': fake.VSERVER_NAME,
|
||||||
|
'expiry_time': 'P' + str(
|
||||||
|
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS) + 'DT',
|
||||||
|
}
|
||||||
|
query1 = {
|
||||||
|
'return_records': 'true'
|
||||||
|
}
|
||||||
|
new_cert_info = copy.deepcopy(
|
||||||
|
fake.SECURITY_CERT_POST_RESPONSE_REST['records'][0])
|
||||||
|
new_cert_uuid = new_cert_info['uuid']
|
||||||
|
new_svm_uuid = new_cert_info['svm']['uuid']
|
||||||
|
body2 = {
|
||||||
|
'certificate': {
|
||||||
|
'uuid': new_cert_uuid,
|
||||||
|
},
|
||||||
|
'client_enabled': 'false',
|
||||||
|
}
|
||||||
|
|
||||||
|
self.client._modify_security_cert(
|
||||||
|
fake.VSERVER_NAME,
|
||||||
|
fake.SECURITY_CERT_LARGE_EXPIRE_DAYS)
|
||||||
|
|
||||||
|
self.client.send_request.assert_has_calls([
|
||||||
|
mock.call('/security/certificates', 'get', query=query),
|
||||||
|
mock.call('/security/certificates', 'post', body=body1,
|
||||||
|
query=query1),
|
||||||
|
mock.call(f'/svm/svms/{new_svm_uuid}', 'patch', body=body2),
|
||||||
|
mock.call(f'/security/certificates/{old_cert_uuid}', 'delete'),
|
||||||
|
])
|
||||||
|
|
||||||
def test__broadcast_domain_exists(self):
|
def test__broadcast_domain_exists(self):
|
||||||
response = fake.FAKE_GET_BROADCAST_DOMAIN
|
response = fake.FAKE_GET_BROADCAST_DOMAIN
|
||||||
|
@ -731,7 +731,8 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
|||||||
fake.NETWORK_INFO)
|
fake.NETWORK_INFO)
|
||||||
self.library._client.create_vserver.assert_called_once_with(
|
self.library._client.create_vserver.assert_called_once_with(
|
||||||
vserver_name, fake.ROOT_VOLUME_AGGREGATE, fake.ROOT_VOLUME,
|
vserver_name, fake.ROOT_VOLUME_AGGREGATE, fake.ROOT_VOLUME,
|
||||||
set(fake.AGGREGATES), fake.IPSPACE)
|
set(fake.AGGREGATES), fake.IPSPACE,
|
||||||
|
fake.SECURITY_CERT_DEFAULT_EXPIRE_DAYS)
|
||||||
self.library._get_api_client.assert_called_once_with(
|
self.library._get_api_client.assert_called_once_with(
|
||||||
vserver=vserver_name)
|
vserver=vserver_name)
|
||||||
self.library._create_vserver_lifs.assert_called_once_with(
|
self.library._create_vserver_lifs.assert_called_once_with(
|
||||||
|
@ -68,6 +68,8 @@ AGGR_POOL_NAME = 'manila_aggr_1'
|
|||||||
FLEXGROUP_POOL_NAME = 'flexgroup_pool'
|
FLEXGROUP_POOL_NAME = 'flexgroup_pool'
|
||||||
ROOT_AGGREGATES = ('root_aggr_1', 'root_aggr_2')
|
ROOT_AGGREGATES = ('root_aggr_1', 'root_aggr_2')
|
||||||
ROOT_VOLUME_AGGREGATE = 'manila1'
|
ROOT_VOLUME_AGGREGATE = 'manila1'
|
||||||
|
SECURITY_CERT_DEFAULT_EXPIRE_DAYS = 365
|
||||||
|
SECURITY_CERT_LARGE_EXPIRE_DAYS = 3652
|
||||||
ROOT_VOLUME = 'root'
|
ROOT_VOLUME = 'root'
|
||||||
CLUSTER_NODE = 'cluster1_01'
|
CLUSTER_NODE = 'cluster1_01'
|
||||||
CLUSTER_NODES = ('cluster1_01', 'cluster1_02')
|
CLUSTER_NODES = ('cluster1_01', 'cluster1_02')
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
NetApp ONTAP driver now allows cloud operator to define security
|
||||||
|
certificate expire days for vserver. So instead of using vserver's default
|
||||||
|
security certificate with 365 expire days, cloud operator can ask backend
|
||||||
|
to create new security certificate with given expire days using config
|
||||||
|
option 'netapp_security_cert_expire_days'.
|
Loading…
Reference in New Issue
Block a user