xds-k8s: PSM Security tests upgrade networksecurity, networkservices to v1beta1 (#27005)

* xds-k8s: PSM Security uses Network Services v1beta1

* xds-k8s: PSM Security uses Network Security v1beta1

* Explain assumptions v1alpha1 extending v1beta1
pull/26973/head^2
Sergii Tkachenko 3 years ago committed by GitHub
parent bbea27de46
commit 1d9a242931
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/api.py
  2. 166
      tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/network_security.py
  3. 122
      tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/network_services.py
  4. 20
      tools/run_tests/xds_k8s_test_driver/framework/infrastructure/traffic_director.py

@ -125,6 +125,8 @@ class GcpApiManager:
version,
api_key=self.private_api_key,
visibility_labels=['NETWORKSECURITY_ALPHA'])
elif version == 'v1beta1':
return self._build_from_discovery_v2(api_name, version)
raise NotImplementedError(f'Network Security {version} not supported')
@ -137,6 +139,8 @@ class GcpApiManager:
version,
api_key=self.private_api_key,
visibility_labels=['NETWORKSERVICES_ALPHA'])
elif version == 'v1beta1':
return self._build_from_discovery_v2(api_name, version)
raise NotImplementedError(f'Network Services {version} not supported')

@ -11,8 +11,11 @@
# 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 abc
import dataclasses
import logging
from typing import Any, Dict
from google.rpc import code_pb2
import tenacity
@ -21,28 +24,53 @@ from framework.infrastructure import gcp
logger = logging.getLogger(__name__)
class NetworkSecurityV1Alpha1(gcp.api.GcpStandardCloudApiResource):
SERVER_TLS_POLICIES = 'serverTlsPolicies'
CLIENT_TLS_POLICIES = 'clientTlsPolicies'
@dataclasses.dataclass(frozen=True)
class ServerTlsPolicy:
url: str
name: str
server_certificate: dict
mtls_policy: dict
update_time: str
create_time: str
@dataclasses.dataclass(frozen=True)
class ClientTlsPolicy:
url: str
name: str
client_certificate: dict
server_validation_ca: list
update_time: str
create_time: str
# Type aliases
GcpResource = gcp.compute.ComputeV1.GcpResource
@dataclasses.dataclass(frozen=True)
class ServerTlsPolicy:
url: str
name: str
server_certificate: dict
mtls_policy: dict
update_time: str
create_time: str
@classmethod
def from_response(cls, name: str, response: Dict[str,
Any]) -> 'ServerTlsPolicy':
return cls(name=name,
url=response['name'],
server_certificate=response.get('serverCertificate', {}),
mtls_policy=response.get('mtlsPolicy', {}),
create_time=response['createTime'],
update_time=response['updateTime'])
@dataclasses.dataclass(frozen=True)
class ClientTlsPolicy:
url: str
name: str
client_certificate: dict
server_validation_ca: list
update_time: str
create_time: str
@classmethod
def from_response(cls, name: str, response: Dict[str,
Any]) -> 'ClientTlsPolicy':
return cls(name=name,
url=response['name'],
client_certificate=response.get('clientCertificate', {}),
server_validation_ca=response.get('serverValidationCa', []),
create_time=response['createTime'],
update_time=response['updateTime'])
class _NetworkSecurityBase(gcp.api.GcpStandardCloudApiResource,
metaclass=abc.ABCMeta):
"""Base class for NetworkSecurity APIs."""
def __init__(self, api_manager: gcp.api.GcpApiManager, project: str):
super().__init__(api_manager.networksecurity(self.api_version), project)
@ -53,68 +81,76 @@ class NetworkSecurityV1Alpha1(gcp.api.GcpStandardCloudApiResource):
def api_name(self) -> str:
return 'networksecurity'
def _execute(self, *args, **kwargs): # pylint: disable=signature-differs
# Workaround TD bug: throttled operations are reported as internal.
# Ref b/175345578
retryer = tenacity.Retrying(
retry=tenacity.retry_if_exception(self._operation_internal_error),
wait=tenacity.wait_fixed(10),
stop=tenacity.stop_after_delay(5 * 60),
before_sleep=tenacity.before_sleep_log(logger, logging.DEBUG),
reraise=True)
retryer(super()._execute, *args, **kwargs)
@staticmethod
def _operation_internal_error(exception):
return (isinstance(exception, gcp.api.OperationError) and
exception.error.code == code_pb2.INTERNAL)
class NetworkSecurityV1Beta1(_NetworkSecurityBase):
"""NetworkSecurity API v1beta1."""
SERVER_TLS_POLICIES = 'serverTlsPolicies'
CLIENT_TLS_POLICIES = 'clientTlsPolicies'
@property
def api_version(self) -> str:
return 'v1alpha1'
return 'v1beta1'
def create_server_tls_policy(self, name, body: dict):
return self._create_resource(self._api_locations.serverTlsPolicies(),
body,
serverTlsPolicyId=name)
def create_server_tls_policy(self, name: str, body: dict) -> GcpResource:
return self._create_resource(
collection=self._api_locations.serverTlsPolicies(),
body=body,
serverTlsPolicyId=name)
def get_server_tls_policy(self, name: str) -> ServerTlsPolicy:
result = self._get_resource(
response = self._get_resource(
collection=self._api_locations.serverTlsPolicies(),
full_name=self.resource_full_name(name, self.SERVER_TLS_POLICIES))
return ServerTlsPolicy.from_response(name, response)
return self.ServerTlsPolicy(name=name,
url=result['name'],
server_certificate=result.get(
'serverCertificate', {}),
mtls_policy=result.get('mtlsPolicy', {}),
create_time=result['createTime'],
update_time=result['updateTime'])
def delete_server_tls_policy(self, name):
def delete_server_tls_policy(self, name: str) -> bool:
return self._delete_resource(
collection=self._api_locations.serverTlsPolicies(),
full_name=self.resource_full_name(name, self.SERVER_TLS_POLICIES))
def create_client_tls_policy(self, name, body: dict):
return self._create_resource(self._api_locations.clientTlsPolicies(),
body,
clientTlsPolicyId=name)
def create_client_tls_policy(self, name: str, body: dict) -> GcpResource:
return self._create_resource(
collection=self._api_locations.clientTlsPolicies(),
body=body,
clientTlsPolicyId=name)
def get_client_tls_policy(self, name: str) -> ClientTlsPolicy:
result = self._get_resource(
response = self._get_resource(
collection=self._api_locations.clientTlsPolicies(),
full_name=self.resource_full_name(name, self.CLIENT_TLS_POLICIES))
return ClientTlsPolicy.from_response(name, response)
return self.ClientTlsPolicy(
name=name,
url=result['name'],
client_certificate=result.get('clientCertificate', {}),
server_validation_ca=result.get('serverValidationCa', []),
create_time=result['createTime'],
update_time=result['updateTime'])
def delete_client_tls_policy(self, name):
def delete_client_tls_policy(self, name: str) -> bool:
return self._delete_resource(
collection=self._api_locations.clientTlsPolicies(),
full_name=self.resource_full_name(name, self.CLIENT_TLS_POLICIES))
def _execute(self, *args, **kwargs): # pylint: disable=signature-differs
# Workaround TD bug: throttled operations are reported as internal.
# Ref b/175345578
retryer = tenacity.Retrying(
retry=tenacity.retry_if_exception(self._operation_internal_error),
wait=tenacity.wait_fixed(10),
stop=tenacity.stop_after_delay(5 * 60),
before_sleep=tenacity.before_sleep_log(logger, logging.DEBUG),
reraise=True)
retryer(super()._execute, *args, **kwargs)
@staticmethod
def _operation_internal_error(exception):
return (isinstance(exception, gcp.api.OperationError) and
exception.error.code == code_pb2.INTERNAL)
class NetworkSecurityV1Alpha1(NetworkSecurityV1Beta1):
"""NetworkSecurity API v1alpha1.
Note: extending v1beta1 class presumes that v1beta1 is just a v1alpha1 API
graduated into a more stable version. This is true in most cases. However,
v1alpha1 class can always override and reimplement incompatible methods.
"""
@property
def api_version(self) -> str:
return 'v1alpha1'

@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import abc
import dataclasses
import logging
from typing import Any, Dict, List, Optional, Tuple
@ -23,8 +24,8 @@ from framework.infrastructure import gcp
logger = logging.getLogger(__name__)
_ComputeV1 = gcp.compute.ComputeV1
GcpResource = _ComputeV1.GcpResource
# Type aliases
GcpResource = gcp.compute.ComputeV1.GcpResource
@dataclasses.dataclass(frozen=True)
@ -32,12 +33,25 @@ class EndpointPolicy:
url: str
name: str
type: str
server_tls_policy: Optional[str]
traffic_port_selector: dict
endpoint_matcher: dict
http_filters: dict
update_time: str
create_time: str
http_filters: Optional[dict] = None
server_tls_policy: Optional[str] = None
@classmethod
def from_response(cls, name: str, response: Dict[str,
Any]) -> 'EndpointPolicy':
return cls(name=name,
url=response['name'],
type=response['type'],
server_tls_policy=response.get('serverTlsPolicy', None),
traffic_port_selector=response['trafficPortSelector'],
endpoint_matcher=response['endpointMatcher'],
http_filters=response.get('httpFilters', None),
update_time=response['updateTime'],
create_time=response['createTime'])
@dataclasses.dataclass(frozen=True)
@ -161,10 +175,9 @@ class GrpcRoute:
)
class NetworkServicesV1Alpha1(gcp.api.GcpStandardCloudApiResource):
ENDPOINT_POLICIES = 'endpointPolicies'
GRPC_ROUTES = 'grpcRoutes'
ROUTERS = 'routers'
class _NetworkServicesBase(gcp.api.GcpStandardCloudApiResource,
metaclass=abc.ABCMeta):
"""Base class for NetworkServices APIs."""
def __init__(self, api_manager: gcp.api.GcpApiManager, project: str):
super().__init__(api_manager.networkservices(self.api_version), project)
@ -175,9 +188,30 @@ class NetworkServicesV1Alpha1(gcp.api.GcpStandardCloudApiResource):
def api_name(self) -> str:
return 'networkservices'
def _execute(self, *args, **kwargs): # pylint: disable=signature-differs
# Workaround TD bug: throttled operations are reported as internal.
# Ref b/175345578
retryer = tenacity.Retrying(
retry=tenacity.retry_if_exception(self._operation_internal_error),
wait=tenacity.wait_fixed(10),
stop=tenacity.stop_after_delay(5 * 60),
before_sleep=tenacity.before_sleep_log(logger, logging.DEBUG),
reraise=True)
retryer(super()._execute, *args, **kwargs)
@staticmethod
def _operation_internal_error(exception):
return (isinstance(exception, gcp.api.OperationError) and
exception.error.code == code_pb2.INTERNAL)
class NetworkServicesV1Beta1(_NetworkServicesBase):
"""NetworkServices API v1beta1."""
ENDPOINT_POLICIES = 'endpointPolicies'
@property
def api_version(self) -> str:
return 'v1alpha1'
return 'v1beta1'
def create_endpoint_policy(self, name, body: dict) -> GcpResource:
return self._create_resource(
@ -186,47 +220,41 @@ class NetworkServicesV1Alpha1(gcp.api.GcpStandardCloudApiResource):
endpointPolicyId=name)
def get_endpoint_policy(self, name: str) -> EndpointPolicy:
result = self._get_resource(
response = self._get_resource(
collection=self._api_locations.endpointPolicies(),
full_name=self.resource_full_name(name, self.ENDPOINT_POLICIES))
return EndpointPolicy(
name=name,
url=result['name'],
type=result['type'],
server_tls_policy=result.get('serverTlsPolicy', None),
traffic_port_selector=result['trafficPortSelector'],
endpoint_matcher=result['endpointMatcher'],
http_filters=result['httpFilters'],
update_time=result['updateTime'],
create_time=result['createTime'])
def delete_endpoint_policy(self, name):
return EndpointPolicy.from_response(name, response)
def delete_endpoint_policy(self, name: str) -> bool:
return self._delete_resource(
collection=self._api_locations.endpointPolicies(),
full_name=self.resource_full_name(name, self.ENDPOINT_POLICIES))
def _execute(self, *args, **kwargs): # pylint: disable=signature-differs
# Workaround TD bug: throttled operations are reported as internal.
# Ref b/175345578
retryer = tenacity.Retrying(
retry=tenacity.retry_if_exception(self._operation_internal_error),
wait=tenacity.wait_fixed(10),
stop=tenacity.stop_after_delay(5 * 60),
before_sleep=tenacity.before_sleep_log(logger, logging.DEBUG),
reraise=True)
retryer(super()._execute, *args, **kwargs)
class NetworkServicesV1Alpha1(NetworkServicesV1Beta1):
"""NetworkServices API v1alpha1.
Note: extending v1beta1 class presumes that v1beta1 is just a v1alpha1 API
graduated into a more stable version. This is true in most cases. However,
v1alpha1 class can always override and reimplement incompatible methods.
"""
GRPC_ROUTES = 'grpcRoutes'
ROUTERS = 'routers'
@property
def api_version(self) -> str:
return 'v1alpha1'
def create_router(self, name: str, body: dict) -> GcpResource:
return self._create_resource(
self._api_locations.routers(),
body,
routerId=name,
)
return self._create_resource(collection=self._api_locations.routers(),
body=body,
routerId=name)
def get_router(self, name: str) -> Router:
full_name = self.resource_full_name(name, self.ROUTERS)
result = self._get_resource(collection=self._api_locations.routers(),
full_name=self.resource_full_name(
name, self.ROUTERS))
full_name=full_name)
return Router.from_response(name, result)
def delete_router(self, name: str) -> bool:
@ -235,22 +263,18 @@ class NetworkServicesV1Alpha1(gcp.api.GcpStandardCloudApiResource):
name, self.ROUTERS))
def create_grpc_route(self, name: str, body: dict) -> GcpResource:
return self._create_resource(self._api_locations.grpcRoutes(),
body,
grpcRouteId=name)
return self._create_resource(
collection=self._api_locations.grpcRoutes(),
body=body,
grpcRouteId=name)
def get_grpc_route(self, name: str) -> GrpcRoute:
full_name = self.resource_full_name(name, self.GRPC_ROUTES)
result = self._get_resource(collection=self._api_locations.grpcRoutes(),
full_name=self.resource_full_name(
name, self.GRPC_ROUTES))
full_name=full_name)
return GrpcRoute.from_response(name, result)
def delete_grpc_route(self, name: str) -> bool:
return self._delete_resource(
collection=self._api_locations.grpcRoutes(),
full_name=self.resource_full_name(name, self.GRPC_ROUTES))
@staticmethod
def _operation_internal_error(exception):
return (isinstance(exception, gcp.api.OperationError) and
exception.error.code == code_pb2.INTERNAL)

@ -14,7 +14,7 @@
import functools
import logging
import random
from typing import Any, Dict, Iterable, List, Optional, Set
from typing import Any, Dict, List, Optional, Set
from framework import xds_flags
from framework.infrastructure import gcp
@ -32,12 +32,13 @@ _BackendGRPC = BackendServiceProtocol.GRPC
_HealthCheckGRPC = HealthCheckProtocol.GRPC
# Network Security
_NetworkSecurityV1Alpha1 = gcp.network_security.NetworkSecurityV1Alpha1
ServerTlsPolicy = _NetworkSecurityV1Alpha1.ServerTlsPolicy
ClientTlsPolicy = _NetworkSecurityV1Alpha1.ClientTlsPolicy
_NetworkSecurityV1Beta1 = gcp.network_security.NetworkSecurityV1Beta1
ServerTlsPolicy = gcp.network_security.ServerTlsPolicy
ClientTlsPolicy = gcp.network_security.ClientTlsPolicy
# Network Services
_NetworkServicesV1Alpha1 = gcp.network_services.NetworkServicesV1Alpha1
_NetworkServicesV1Beta1 = gcp.network_services.NetworkServicesV1Beta1
EndpointPolicy = gcp.network_services.EndpointPolicy
# Testing metadata consts
@ -537,6 +538,8 @@ class TrafficDirectorAppNetManager(TrafficDirectorManager):
GRPC_ROUTE_NAME = "grpc-route"
ROUTER_NAME = "router"
netsvc: _NetworkServicesV1Alpha1
def __init__(self,
gcp_api_manager: gcp.api.GcpApiManager,
project: str,
@ -627,12 +630,14 @@ class TrafficDirectorAppNetManager(TrafficDirectorManager):
class TrafficDirectorSecureManager(TrafficDirectorManager):
netsec: Optional[_NetworkSecurityV1Alpha1]
SERVER_TLS_POLICY_NAME = "server-tls-policy"
CLIENT_TLS_POLICY_NAME = "client-tls-policy"
ENDPOINT_POLICY = "endpoint-policy"
CERTIFICATE_PROVIDER_INSTANCE = "google_cloud_private_spiffe"
netsec: _NetworkSecurityV1Beta1
netsvc: _NetworkServicesV1Beta1
def __init__(
self,
gcp_api_manager: gcp.api.GcpApiManager,
@ -649,8 +654,8 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
network=network)
# API
self.netsec = _NetworkSecurityV1Alpha1(gcp_api_manager, project)
self.netsvc = _NetworkServicesV1Alpha1(gcp_api_manager, project)
self.netsec = _NetworkSecurityV1Beta1(gcp_api_manager, project)
self.netsvc = _NetworkServicesV1Beta1(gcp_api_manager, project)
# Managed resources
self.server_tls_policy: Optional[ServerTlsPolicy] = None
@ -734,7 +739,6 @@ class TrafficDirectorSecureManager(TrafficDirectorManager):
}
config = {
"type": "GRPC_SERVER",
"httpFilters": {},
"trafficPortSelector": port_selector,
"endpointMatcher": {
"metadataLabelMatcher": label_matcher_all,

Loading…
Cancel
Save