Esempio n. 1
0
    def test_grpc_error_intercept(self, kube_apis, ingress_controller_prerequisites, crd_ingress_controller, 
                                  backend_setup, virtual_server_setup):
        cert = get_certificate(virtual_server_setup.public_endpoint.public_ip,
                               virtual_server_setup.vs_host,
                               virtual_server_setup.public_endpoint.port_ssl)
        target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}'
        credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode())
        options = (('grpc.ssl_target_name_override', virtual_server_setup.vs_host),)

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            response = ""
            try:
                response = stub.SayHello(HelloRequest(name=virtual_server_setup.public_endpoint.public_ip))
                valid_message = "Hello {}".format(virtual_server_setup.public_endpoint.public_ip)
                # no status has been returned in the response
                assert valid_message in response.message
            except grpc.RpcError as e:
                print(e.details())
                pytest.fail("RPC error was not expected during call, exiting...")
        # Assert grpc_status is in the logs. The gRPC response in a successful call is 0.
        ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
        log_contents = kube_apis.v1.read_namespaced_pod_log(ic_pod_name, ingress_controller_prerequisites.namespace)
        retry = 0
        while '"POST /helloworld.Greeter/SayHello HTTP/2.0" 200 0' not in log_contents and retry <= 60:
            log_contents = kube_apis.v1.read_namespaced_pod_log(
                ic_pod_name, ingress_controller_prerequisites.namespace)
            retry += 1
            wait_before_test(1)
            print(f"Logs not yet updated, retrying... #{retry}")
        assert '"POST /helloworld.Greeter/SayHello HTTP/2.0" 200 0' in log_contents

        scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "grpc1", virtual_server_setup.namespace, 0)
        scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "grpc2", virtual_server_setup.namespace, 0)
        wait_before_test()

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            try:
                response = stub.SayHello(HelloRequest(name=virtual_server_setup.public_endpoint.public_ip))
                # assert the grpc status has been returned in the header
                assert response.status == 14
                pytest.fail("RPC error was expected during call, exiting...")
            except grpc.RpcError as e:
                print(e)
        # Assert the grpc_status is also in the logs.
        ic_pod_name = get_first_pod_name(kube_apis.v1, ingress_controller_prerequisites.namespace)
        wait_before_test()
        # Need to get full log because of a race condition on the last log entry.
        log_contents = kube_apis.v1.read_namespaced_pod_log(ic_pod_name, ingress_controller_prerequisites.namespace)
        retry = 0
        while '"POST /helloworld.Greeter/SayHello HTTP/2.0" 204 14' not in log_contents and retry <= 60:
            log_contents = kube_apis.v1.read_namespaced_pod_log(
                ic_pod_name, ingress_controller_prerequisites.namespace)
            retry += 1
            wait_before_test(1)
            print(f"Logs not yet updated, retrying... #{retry}")
Esempio n. 2
0
    def test_connect_grpc_backend(self, kube_apis,
                                  ingress_controller_prerequisites,
                                  crd_ingress_controller, backend_setup,
                                  virtual_server_setup) -> None:
        cert = get_certificate(virtual_server_setup.public_endpoint.public_ip,
                               virtual_server_setup.vs_host,
                               virtual_server_setup.public_endpoint.port_ssl)
        target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}'
        credentials = grpc.ssl_channel_credentials(
            root_certificates=cert.encode())
        options = (('grpc.ssl_target_name_override',
                    virtual_server_setup.vs_host), )

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            response = ""
            try:
                response = stub.SayHello(
                    HelloRequest(
                        name=virtual_server_setup.public_endpoint.public_ip))
                valid_message = "Hello {}".format(
                    virtual_server_setup.public_endpoint.public_ip)
                assert valid_message in response.message
            except grpc.RpcError as e:
                print(e.details())
                pytest.fail(
                    "RPC error was not expected during call, exiting...")
Esempio n. 3
0
    def test_grpc_error_intercept(self, kube_apis,
                                  ingress_controller_prerequisites,
                                  crd_ingress_controller, backend_setup,
                                  virtual_server_setup):
        cert = get_certificate(virtual_server_setup.public_endpoint.public_ip,
                               virtual_server_setup.vs_host,
                               virtual_server_setup.public_endpoint.port_ssl)
        target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}'
        credentials = grpc.ssl_channel_credentials(
            root_certificates=cert.encode())
        options = (('grpc.ssl_target_name_override',
                    virtual_server_setup.vs_host), )

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            response = ""
            try:
                response = stub.SayHello(
                    HelloRequest(
                        name=virtual_server_setup.public_endpoint.public_ip))
                valid_message = "Hello {}".format(
                    virtual_server_setup.public_endpoint.public_ip)
                # no status has been returned in the response
                assert valid_message in response.message
            except grpc.RpcError as e:
                print(e.details())
                pytest.fail(
                    "RPC error was not expected during call, exiting...")

        scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "grpc1",
                         virtual_server_setup.namespace, 0)
        scale_deployment(kube_apis.v1, kube_apis.apps_v1_api, "grpc2",
                         virtual_server_setup.namespace, 0)
        time.sleep(1)

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            try:
                response = stub.SayHello(
                    HelloRequest(
                        name=virtual_server_setup.public_endpoint.public_ip))
                # assert the grpc status has been returned in the header
                assert response.status == 14
                pytest.fail("RPC error was expected during call, exiting...")
            except grpc.RpcError as e:
                print(e)
    def test_responses_grpc_block(self, kube_apis,
                                  crd_ingress_controller_with_ap,
                                  backend_setup, test_namespace):
        """
        Test grpc-block-hello AppProtect policy: Blocks /sayhello gRPC method only
        Client sends request to /sayhello
        """
        syslog_pod = kube_apis.v1.list_namespaced_pod(
            test_namespace).items[-1].metadata.name

        # we need to get the cert so that it can be used in credentials in grpc.secure_channel to verify itself.
        # without verification, we will not be able to use the channel
        cert = get_certificate(backend_setup.ip, backend_setup.ingress_host,
                               backend_setup.port_ssl)

        target = f'{backend_setup.ip}:{backend_setup.port_ssl}'
        credentials = grpc.ssl_channel_credentials(
            root_certificates=cert.encode())

        # this option is necessary to set the SNI of a gRPC connection and it only works with grpc.secure_channel.
        # also, the TLS cert for the Ingress must have the CN equal to backend_setup.ingress_host
        options = (('grpc.ssl_target_name_override',
                    backend_setup.ingress_host), )

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            ex = ""
            try:
                stub.SayHello(HelloRequest(name=backend_setup.ip))
                pytest.fail("RPC error was expected during call, exiting...")
            except grpc.RpcError as e:
                # grpc.RpcError is also grpc.Call https://grpc.github.io/grpc/python/grpc.html#client-side-context
                ex = e.details()
                print(ex)

        log_contents = ""
        retry = 0
        while "ASM:attack_type" not in log_contents and retry <= 30:
            log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod,
                                             test_namespace)
            retry += 1
            wait_before_test(1)
            print(f"Security log not updated, retrying... #{retry}")

        assert (invalid_resp_text in ex
                and 'ASM:attack_type="Directory Indexing"' in log_contents
                and 'violations="Illegal gRPC method"' in log_contents
                and 'severity="Error"' in log_contents
                and 'outcome="REJECTED"' in log_contents)
def grpc_waf_allow(kube_apis, test_namespace, public_ip, vs_host, port_ssl):
    cert = get_certificate(public_ip, vs_host, port_ssl)
    target = f'{public_ip}:{port_ssl}'
    credentials = grpc.ssl_channel_credentials(root_certificates=cert.encode())
    options = (('grpc.ssl_target_name_override', vs_host), )

    with grpc.secure_channel(target, credentials, options) as channel:
        stub = GreeterStub(channel)
        response = ""
        try:
            response = stub.SayHello(HelloRequest(name=public_ip))
            print(response)
        except grpc.RpcError as e:
            print(e.details())
            pytest.fail("RPC error was not expected during call, exiting...")
    assert valid_resp_txt in response.message
    def test_config_after_setup(self, kube_apis,
                                ingress_controller_prerequisites,
                                crd_ingress_controller, backend_setup,
                                virtual_server_setup):
        print("\nStep 1: assert config")
        ic_pod_name = get_first_pod_name(
            kube_apis.v1, ingress_controller_prerequisites.namespace)
        config = get_vs_nginx_template_conf(
            kube_apis.v1, virtual_server_setup.namespace,
            virtual_server_setup.vs_name, ic_pod_name,
            ingress_controller_prerequisites.namespace)

        assert_grpc_entries_exist(config)
        assert_proxy_entries_exist(config)

        print("\nStep 2: check connection to http backend")
        print("\nrequest URL: ", virtual_server_setup.backend_2_url)
        resp = requests.get(virtual_server_setup.backend_2_url,
                            headers={"host": virtual_server_setup.vs_host})
        print("Response from http backend: {}".format(resp))
        assert resp.status_code == 200

        print("\nStep 3: Check connection to app")
        cert = get_certificate(virtual_server_setup.public_endpoint.public_ip,
                               virtual_server_setup.vs_host,
                               virtual_server_setup.public_endpoint.port_ssl)
        target = f'{virtual_server_setup.public_endpoint.public_ip}:{virtual_server_setup.public_endpoint.port_ssl}'
        credentials = grpc.ssl_channel_credentials(
            root_certificates=cert.encode())
        options = (('grpc.ssl_target_name_override',
                    virtual_server_setup.vs_host), )

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            response = ""
            try:
                response = stub.SayHello(
                    HelloRequest(
                        name=virtual_server_setup.public_endpoint.public_ip))
                valid_message = "Hello {}".format(
                    virtual_server_setup.public_endpoint.public_ip)
                assert valid_message in response.message
            except grpc.RpcError as e:
                print(e.details())
                pytest.fail(
                    "RPC error was not expected during call, exiting...")
    def test_responses_grpc_allow(self, kube_apis,
                                  crd_ingress_controller_with_ap,
                                  backend_setup, test_namespace,
                                  ingress_controller_endpoint):
        """
        Test grpc-block-goodbye AppProtect policy: Blocks /saygoodbye gRPC method only
        Client sends request to /sayhello thus should pass
        """
        syslog_pod = kube_apis.v1.list_namespaced_pod(
            test_namespace).items[-1].metadata.name
        cert = get_certificate(backend_setup.ip, backend_setup.ingress_host,
                               backend_setup.port_ssl)

        target = f'{backend_setup.ip}:{backend_setup.port_ssl}'
        credentials = grpc.ssl_channel_credentials(
            root_certificates=cert.encode())
        options = (('grpc.ssl_target_name_override',
                    backend_setup.ingress_host), )

        with grpc.secure_channel(target, credentials, options) as channel:
            stub = GreeterStub(channel)
            response = ""
            try:
                response = stub.SayHello(HelloRequest(name=backend_setup.ip))
                print(response)
            except grpc.RpcError as e:
                print(e.details())
                pytest.fail(
                    "RPC error was not expected during call, exiting...")

        log_contents = ""
        retry = 0
        while "ASM:attack_type" not in log_contents and retry <= 30:
            log_contents = get_file_contents(kube_apis.v1, log_loc, syslog_pod,
                                             test_namespace)
            retry += 1
            wait_before_test(1)
            print(f"Security log not updated, retrying... #{retry}")

        assert (valid_resp_txt in response.message
                and 'ASM:attack_type="N/A"' in log_contents
                and 'violations="N/A"' in log_contents
                and 'severity="Informational"' in log_contents
                and 'outcome="PASSED"' in log_contents)