Example #1
0
async def test_appsync_subscription_iam_not_allowed(event_loop, server):

    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from gql.transport.exceptions import TransportQueryError
    from botocore.credentials import Credentials

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    dummy_credentials = Credentials(
        access_key=DUMMY_ACCESS_KEY_ID_NOT_ALLOWED,
        secret_key=DUMMY_SECRET_ACCESS_KEY,
        token=DUMMY_SECRET_SESSION_TOKEN,
    )

    auth = AppSyncIAMAuthentication(host=server.hostname,
                                    credentials=dummy_credentials,
                                    region_name=REGION_NAME)

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    client = Client(transport=transport)

    async with client as session:
        subscription = gql(on_create_message_subscription_str)

        with pytest.raises(TransportQueryError) as exc_info:

            async for result in session.subscribe(subscription):
                pass

        assert "Permission denied" in str(exc_info)
Example #2
0
async def main():

    # Should look like:
    # https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
    url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")

    if url is None:
        print("Missing environment variables")
        sys.exit()

    # Using implicit auth (IAM)
    transport = AppSyncWebsocketsTransport(url=url)

    async with Client(transport=transport) as session:

        subscription = gql("""
subscription onCreateMessage {
  onCreateMessage {
    message
  }
}
""")

        print("Waiting for messages...")

        async for result in session.subscribe(subscription):
            print(result)
async def main():

    # Should look like:
    # https://XXXXXXXXXXXXXXXXXXXXXXXXXX.appsync-api.REGION.amazonaws.com/graphql
    url = os.environ.get("AWS_GRAPHQL_API_ENDPOINT")
    api_key = os.environ.get("AWS_GRAPHQL_API_KEY")

    if url is None or api_key is None:
        print("Missing environment variables")
        sys.exit()

    # Extract host from url
    host = str(urlparse(url).netloc)

    print(f"Host: {host}")

    auth = AppSyncApiKeyAuthentication(host=host, api_key=api_key)

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    async with Client(transport=transport) as session:

        subscription = gql("""
subscription onCreateMessage {
  onCreateMessage {
    message
  }
}
""")

        print("Waiting for messages...")

        async for result in session.subscribe(subscription):
            print(result)
Example #4
0
def test_appsync_init_with_iam_auth_and_no_region(caplog,
                                                  fake_credentials_factory,
                                                  fake_session_factory):
    """

    WARNING: this test will fail if:
     - you have a default region set in ~/.aws/config
     - you have the AWS_DEFAULT_REGION environment variable set

    """
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from botocore.exceptions import NoRegionError
    import logging

    caplog.set_level(logging.WARNING)

    with pytest.raises(NoRegionError):
        session = fake_session_factory(credentials=fake_credentials_factory())
        session._region_name = None
        session._credentials.region = None
        transport = AppSyncWebsocketsTransport(url=mock_transport_url,
                                               session=session)

        # prints the region name in case the test fails
        print(f"Region found: {transport.auth._region_name}")

    print(f"Captured: {caplog.text}")

    expected_error = (
        "Region name not found. "
        "It was not possible to detect your region either from the host "
        "or from your default AWS configuration.")

    assert expected_error in caplog.text
Example #5
0
def test_appsync_init_with_iam_auth_without_creds(fake_session_factory):
    import botocore.exceptions
    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    auth = AppSyncIAMAuthentication(
        host=mock_transport_host,
        session=fake_session_factory(credentials=None),
    )
    with pytest.raises(botocore.exceptions.NoCredentialsError):
        AppSyncWebsocketsTransport(url=mock_transport_url, auth=auth)
Example #6
0
def test_appsync_init_with_iam_auth_with_creds(fake_credentials_factory):
    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    auth = AppSyncIAMAuthentication(
        host=mock_transport_host,
        credentials=fake_credentials_factory(),
        region_name="us-east-1",
    )
    sample_transport = AppSyncWebsocketsTransport(url=mock_transport_url,
                                                  auth=auth)
    assert sample_transport.auth is auth
Example #7
0
def test_appsync_init_with_minimal_args(fake_session_factory):
    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    sample_transport = AppSyncWebsocketsTransport(
        url=mock_transport_url, session=fake_session_factory())
    assert isinstance(sample_transport.auth, AppSyncIAMAuthentication)
    assert sample_transport.connect_timeout == 10
    assert sample_transport.close_timeout == 10
    assert sample_transport.ack_timeout == 10
    assert sample_transport.ssl is False
    assert sample_transport.connect_args == {}
Example #8
0
def test_appsync_init_with_jwt_auth():
    from gql.transport.appsync_auth import AppSyncJWTAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    auth = AppSyncJWTAuthentication(host=mock_transport_host, jwt="some-jwt")
    sample_transport = AppSyncWebsocketsTransport(url=mock_transport_url,
                                                  auth=auth)
    assert sample_transport.auth is auth

    assert auth.get_headers() == {
        "host": mock_transport_host,
        "Authorization": "some-jwt",
    }
Example #9
0
def test_appsync_init_with_apikey_auth():
    from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    auth = AppSyncApiKeyAuthentication(host=mock_transport_host,
                                       api_key="some-api-key")
    sample_transport = AppSyncWebsocketsTransport(url=mock_transport_url,
                                                  auth=auth)
    assert sample_transport.auth is auth

    assert auth.get_headers() == {
        "host": mock_transport_host,
        "x-api-key": "some-api-key",
    }
Example #10
0
async def test_appsync_subscription_api_key(event_loop, server):

    from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    auth = AppSyncApiKeyAuthentication(host=server.hostname,
                                       api_key=DUMMY_API_KEY)

    transport = AppSyncWebsocketsTransport(
        url=url, auth=auth, keep_alive_timeout=(5 * SEND_MESSAGE_DELAY))

    await default_transport_test(transport)
Example #11
0
def test_appsync_init_with_no_credentials(caplog, fake_session_factory):
    import botocore.exceptions
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    with pytest.raises(botocore.exceptions.NoCredentialsError):
        sample_transport = AppSyncWebsocketsTransport(
            url=mock_transport_url,
            session=fake_session_factory(credentials=None),
        )
        assert sample_transport.auth is None

    expected_error = "Credentials not found"

    print(f"Captured log: {caplog.text}")

    assert expected_error in caplog.text
Example #12
0
async def test_appsync_subscription_variable_values_and_operation_name(
        event_loop, server):

    from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    auth = AppSyncApiKeyAuthentication(host=server.hostname,
                                       api_key=DUMMY_API_KEY)

    transport = AppSyncWebsocketsTransport(
        url=url, auth=auth, keep_alive_timeout=(5 * SEND_MESSAGE_DELAY))

    client = Client(transport=transport)

    expected_messages = [
        f"Hello world {number}!" for number in range(NB_MESSAGES)
    ]
    received_messages = []

    async with client as session:
        subscription = gql(on_create_message_subscription_str)

        async for execution_result in session.subscribe(
                subscription,
                operation_name="onCreateMessage",
                variable_values={"key1": "val1"},
                get_execution_result=True,
        ):

            result = execution_result.data
            message = result["onCreateMessage"]["message"]
            print(f"Message received: '{message}'")

            received_messages.append(message)

            print(f"extensions received: {execution_result.extensions}")

            assert execution_result.extensions[
                "operation_name"] == "onCreateMessage"
            variables = execution_result.extensions["variables"]
            assert variables["key1"] == "val1"

    assert expected_messages == received_messages
Example #13
0
def test_munge_url(fake_signer_factory, fake_request_factory):
    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

    test_url = "https://appsync-api.aws.example.org/some-other-params"

    auth = AppSyncIAMAuthentication(
        host=test_url,
        signer=fake_signer_factory(),
        request_creator=fake_request_factory,
    )
    sample_transport = AppSyncWebsocketsTransport(url=test_url, auth=auth)

    header_string = ("eyJGYWtlQXV0aG9yaXphdGlvbiI6ImEiLCJGYWtlVGltZSI6InRvZGF5"
                     "IiwiaG9zdCI6Imh0dHBzOi8vYXBwc3luYy1hcGkuYXdzLmV4YW1wbGUu"
                     "b3JnL3NvbWUtb3RoZXItcGFyYW1zIn0=")
    expected_url = ("wss://appsync-realtime-api.aws.example.org/"
                    f"some-other-params?header={header_string}&payload=e30=")
    assert sample_transport.url == expected_url
Example #14
0
async def test_appsync_subscription_api_key_unauthorized(event_loop, server):

    from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from gql.transport.exceptions import TransportServerError

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    auth = AppSyncApiKeyAuthentication(host=server.hostname, api_key="invalid")

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    client = Client(transport=transport)

    with pytest.raises(TransportServerError) as exc_info:
        async with client as _:
            pass

    assert "You are not authorized to make this call." in str(exc_info)
Example #15
0
async def test_appsync_execute_method_not_allowed(event_loop, server):

    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from botocore.credentials import Credentials

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    dummy_credentials = Credentials(
        access_key=DUMMY_ACCESS_KEY_ID,
        secret_key=DUMMY_SECRET_ACCESS_KEY,
    )

    auth = AppSyncIAMAuthentication(host=server.hostname,
                                    credentials=dummy_credentials,
                                    region_name=REGION_NAME)

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    client = Client(transport=transport)

    async with client as session:
        query = gql("""
mutation createMessage($message: String!) {
  createMessage(input: {message: $message}) {
    id
    message
    createdAt
  }
}""")

        variable_values = {"message": "Hello world!"}

        with pytest.raises(AssertionError) as exc_info:
            await session.execute(query, variable_values=variable_values)

        assert (
            "execute method is not allowed for AppSyncWebsocketsTransport "
            "because only subscriptions are allowed on the realtime endpoint."
        ) in str(exc_info)
Example #16
0
async def test_appsync_subscription_iam_without_token(event_loop, server):

    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from botocore.credentials import Credentials

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    dummy_credentials = Credentials(
        access_key=DUMMY_ACCESS_KEY_ID,
        secret_key=DUMMY_SECRET_ACCESS_KEY,
    )

    auth = AppSyncIAMAuthentication(host=server.hostname,
                                    credentials=dummy_credentials,
                                    region_name=REGION_NAME)

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    await default_transport_test(transport)
Example #17
0
async def test_appsync_subscription_server_sending_an_error_without_an_id(
        event_loop, server):

    from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from gql.transport.exceptions import TransportServerError

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    auth = AppSyncApiKeyAuthentication(host=server.hostname,
                                       api_key=DUMMY_API_KEY)

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    client = Client(transport=transport)

    with pytest.raises(TransportServerError) as exc_info:
        async with client as _:
            pass

    assert "Sometimes AppSync will send you an error without an id" in str(
        exc_info)
Example #18
0
async def test_appsync_subscription_server_sending_a_not_json_answer(
        event_loop, server):

    from gql.transport.appsync_auth import AppSyncApiKeyAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from gql.transport.exceptions import TransportProtocolError

    path = "/graphql"
    url = f"ws://{server.hostname}:{server.port}{path}"

    auth = AppSyncApiKeyAuthentication(host=server.hostname,
                                       api_key=DUMMY_API_KEY)

    transport = AppSyncWebsocketsTransport(url=url, auth=auth)

    client = Client(transport=transport)

    with pytest.raises(TransportProtocolError) as exc_info:
        async with client as _:
            pass

    assert "Server did not return a GraphQL result: Something not json" in str(
        exc_info)
Example #19
0
async def test_appsync_fetch_schema_from_transport_not_allowed(event_loop):

    from gql.transport.appsync_auth import AppSyncIAMAuthentication
    from gql.transport.appsync_websockets import AppSyncWebsocketsTransport
    from botocore.credentials import Credentials

    dummy_credentials = Credentials(
        access_key=DUMMY_ACCESS_KEY_ID,
        secret_key=DUMMY_SECRET_ACCESS_KEY,
    )

    auth = AppSyncIAMAuthentication(host="something",
                                    credentials=dummy_credentials,
                                    region_name=REGION_NAME)

    transport = AppSyncWebsocketsTransport(url="https://something", auth=auth)

    with pytest.raises(AssertionError) as exc_info:
        Client(transport=transport, fetch_schema_from_transport=True)

    assert (
        "fetch_schema_from_transport=True is not allowed for AppSyncWebsocketsTransport"
        " because only subscriptions are allowed on the realtime endpoint."
    ) in str(exc_info)
Example #20
0
def get_transport(args: Namespace) -> Optional[AsyncTransport]:
    """Instantiate a transport from the parsed command line arguments

    :param args: parsed command line arguments
    """

    # Get the url scheme from server parameter
    url = URL(args.server)

    # Validate scheme
    if url.scheme not in ["http", "https", "ws", "wss"]:
        raise ValueError("URL protocol should be one of: http, https, ws, wss")

    # Get extra transport parameters from command line arguments
    # (headers)
    transport_args = get_transport_args(args)

    # Either use the requested transport or autodetect it
    if args.transport == "auto":
        transport_name = autodetect_transport(url)
    else:
        transport_name = args.transport

    # Import the correct transport class depending on the transport name
    if transport_name == "aiohttp":
        from gql.transport.aiohttp import AIOHTTPTransport

        return AIOHTTPTransport(url=args.server, **transport_args)

    elif transport_name == "phoenix":
        from gql.transport.phoenix_channel_websockets import (
            PhoenixChannelWebsocketsTransport,
        )

        return PhoenixChannelWebsocketsTransport(url=args.server, **transport_args)

    elif transport_name == "websockets":
        from gql.transport.websockets import WebsocketsTransport

        transport_args["ssl"] = url.scheme == "wss"

        return WebsocketsTransport(url=args.server, **transport_args)

    else:

        from gql.transport.appsync_auth import AppSyncAuthentication

        assert transport_name in ["appsync_http", "appsync_websockets"]
        assert url.host is not None

        auth: AppSyncAuthentication

        if args.api_key:
            from gql.transport.appsync_auth import AppSyncApiKeyAuthentication

            auth = AppSyncApiKeyAuthentication(host=url.host, api_key=args.api_key)

        elif args.jwt:
            from gql.transport.appsync_auth import AppSyncJWTAuthentication

            auth = AppSyncJWTAuthentication(host=url.host, jwt=args.jwt)

        else:
            from gql.transport.appsync_auth import AppSyncIAMAuthentication
            from botocore.exceptions import NoRegionError

            try:
                auth = AppSyncIAMAuthentication(host=url.host)
            except NoRegionError:
                # A warning message has been printed in the console
                return None

        transport_args["auth"] = auth

        if transport_name == "appsync_http":
            from gql.transport.aiohttp import AIOHTTPTransport

            return AIOHTTPTransport(url=args.server, **transport_args)

        else:
            from gql.transport.appsync_websockets import AppSyncWebsocketsTransport

            try:
                return AppSyncWebsocketsTransport(url=args.server, **transport_args)
            except Exception:
                # This is for the NoCredentialsError but we cannot import it here
                return None