Private, cross-account GraphQL APIs with AppSync Merged APIs

Antonio Lagrotteria
Towards AWS
Published in
9 min readJun 10, 2023

--

In the realm of distributed systems and secure data sharing, GraphQL has become a valuable option for engineers.

AppSync, AWS GraphQL offering has recently released two very promising features: Merged and Private APIs:

  • Private APIs restrict access to GraphQL APIs to clients within a private network and allowed principals, such as AWS Accounts, VPCs or on-premises data centres.
  • Merged APIs enable teams to merge resources (types, data sources, functions, resolvers) from multiple source AppSync APIs into a single, consolidated and unified AppSync endpoint.

This article provides a step-by-step guide to combining the two releases and exposing two private AppSync APIs through a public AppSync Merged API, providing the benefits of both releases.

Architecture

The architecture involves four accounts:

  • AccountManagement: the account responsible for managing the AWS Organizational Units (OUs) via AWS Organizations.
  • AccountA: hosting a private GraphQL API handling generic products.
  • AccountB: hosting a private GraphQL API handing orders.
  • AccountMerge, hosting the public merged GraphQL API.

The private GraphQL APIs will be shared with the public facing API via Resource Access Manager (RAM).

0. Prerequisites

0.1 Setup Organizations

Before you can start creating the APIs, we need to structure our cross-accounts setup.

  • Create/reuse an AWS account responsible for managing AWS Organizations, here called AccountManagement.
  • In the same account, go to AWS Organizations and create an Organization.
  • Start adding or inviting AWS accounts.
  • Create/invite AccountA, AccountB and AccountMerge similarly.
  • Optionally, you can place the accounts under Organizational Units (OUs) for better management.
  • The Organizational structure should look as this:

For tutorials/troubleshooting on AWS Organizations (out of the scope of this article), please refer to the following:

0.2 Share resources

One last step is to enable sharing on this account. This step is required as I will be sharing private AppSync APIs via Resource Access Manager (RAM), a service that simplifies the process of sharing resources among AWS accounts. To enable resource sharing within your organization:

  • Open the Settings page in the AWS RAM console.
  • Choose Enable sharing with AWS Organizations, and then choose Save settings.

Let’s now follow the steps to create 2 private APIs and share them with the public Merge API.

1. Create a Product, Private AppSync API

Let’s now create a simple Product API. This will be a private AppSync endpoint, as it can only be accessed by VPC.

  • Go to AccountA.
  • Go to AppSync and Create an API.
  • Create a Product API in AppSync. This starts the Create API Wizard, which has 4 steps.

1.1 Select API Type

Select GraphQL APIs and Design from scratch

1.2 Specify API metadata

Add the API name and select “Use private API features” and thenNext”.

1.3 Specify GrapQL resources

Create a GrapthQL type backed by a DynamoDB. The table is based on a Product model which 4 fields (id, title, description and createdAt) and a primary key. Click “Next”.

1.4 Review and create

Finally, review the wizard data and click “Create API”.

That’s it. A new private GraphQL API is not created. The next step is to share it with the account which will hold the public Merge API.

2. Share the Product API

To share the API, we will use the RAM service. It is a very cool and underestimated service which allows you to share AWS resources across multiple accounts in a controlled and secure manner. Essentially we will create a shared resource, which refers to an AWS service or component (e.g. an AppSync API…) that can be accessed and utilized by multiple AWS accounts or users within an organization. Let’s see how.

  • Take note of the AWS Account id for the AccountMerge one.
  • In the same account (AccountA), go to RAM.
  • Click on “Create resource share”, which will start a wizard.

The wizard consists of 4 steps:

2.1 Specify resource share details

This step requires you to provide a name for the resource share, along with the resource itself. You can find the resource by filtering the search and searching for “AppSync GraphQL APIs”. Since RAM is a regional service, make sure you are in the same region as you created the AppSync API. If that is the case, the API will appear in the resources list. Select it and click “Next”. The below pictures summarize the sub-steps:

2.2 Associate managed permissions

This important step specifies which actions principals are allowed to perform on shared resources.

  • Click the “Create a customer managed permissions” button.
  • This opens a new tab where you can define which actions the principals can perform on a resource type in a resource share. Provide a name (e.g. AWSRAMAssociatedMergedAPIAccess) and select “All actions”. This is needed as the accounts’ Merge API must have the appsync:AssociateMergedGraphqlApi access level in order to associate the private API with the Merge one correctly.
  • Finally, click the “Create a customer managed permissions” button located in the new tab. The below picture summarizes the described flow:
  • Now, back to the Create share resource tab, select the newly created customer managed permission and click “Next”.

2.3 Grant access to principals

This step defines the principals that are allowed access to the shared resources. Principals can be part of the same Organization (recommended) or not.

  • Click “Allow sharing only within your organization”.
  • Grab the AccountMerge account id and paste it in the input field.
  • Click “Add”.
  • Select the Principal below
  • Click “Next”.

The below picture gives an overview of the flow:

2.4 Review and create

The last step is just to review and finalize the Create resource share wizard; do so and click Create resource share button.

3. Create an Order, Private AppSync API

The second private AppSync API to be created is about orders. Essentially, you should repeat the same steps as section 2 but applied for an Orders API.

  • Go to AccountB
  • Go to Appsync and Create an API.
  • Follow the steps in Section 1, but. this time, you should create an Order model. An example would be to have 3 fields (id, quantity, productId), with a partition key for the order id (id field) and a global secondary index to query products.
  • Finalize the wizard and provision the API.

By the end of this step, you must have an Orders API similar to the below:

4. Share the Order API

Now you must repeat the same steps in section 2, but instead, you need to share the orders API with the AccountMerge. This is the account hosting the Merge API which we are going to create in the next section.

The shared resource should look like this:

Now comes the time to glue the two APIs into a single, unified Merge API.

5. Create the Merged API

Finally, it is time to put all pieces together. The goal is to create a public-facing AppSync API which will merge both the Products and Orders private APIs. To do so:

  • Go to the AccountMerge account
  • Go to AppSync
  • Create an API and start the wizard.

5.1 Select API Type

This time, we need to select “Merged APIs” and click “Next”.

5.2 Specify API metadata

  • Provide a name (e.g. MergedProductsAndOrdersAPI)
  • Choose “Create and use a new service role”, as the new merged API requires an IAM role for AWS AppSync to access the imported source API resources at runtime securely.
  • Click “Next”.

5.3 Select Sources API

This step allows you to associate the private API created in sections 1 (Products) and 3 (Orders).

  • As they are located in different AWS accounts, click the “Add Source API” button with the “APIs from other AWS accounts” area.
  • As we shared both private APIs in section 2 and 4, they are now visible in this modal. Select them and click “Add Source APIs”
  • Now that Source APIs have been chosen click “Next”.

5.4 Select authorization mode

This step requires you to select the authorization mode you want to protect the Merged API with.

  • For simplicity, we choose “API key”.
  • Click “Next”.

More authorizations mode can be seen here:

5.5 Review and create

Finally, review the wizard data and click “Create API”. Now it is time to test the API.

6. Testing the API

To test the API, we can just use the Query editor. Already from there, you can appreciate the result of this merged API:

Mutations, queries and subscriptions of both APIs have been merged!

Nevertheless, if you now try, for instance, to create a new product, you will encounter this issue:

Not authorized to perform: appsync:SourceGraphQL on resource arn:aws:appsync:<region>:<account_id>:apis/<api_id>

To fix this, we must modify the Merged API execution IAM role, created during its wizard.

  • Go to your Merged API
  • On the left side, click Settings
  • On the API menu, you will find the execution role link; click it.
  • You will land in the IAM role. Here, you have full freedom in the way you want to allow the permission. This is one example:
{
"Effect": "Allow",
"Action": [
"appsync:SourceGraphQL"
],
"Resource": [
"arn:aws:appsync:<REGION>:<ACCOUNT_ID>:apis/<APPSYNC_API_ID>/types/*/fields/*"
]
}
  • Save the role.
  • Go back now to the query editor and this time both creation of products, orders and listing works.

7. Conclusion

I hope you reached the end of this guide! Congrats.

This article provided a comprehensive guide on how to create private GraphQL APIs using AWS AppSync and then merge them into a single public API. By leveraging the features of private APIs and the AppSync Merge API, organizations can address challenges related to API security and cross-team collaboration. This approach enables the consolidation of multiple private APIs into a unified endpoint, offering the benefits of both private access and centralized management.

PlainEnglish.io 🚀

Thank you for being a part of the In Plain English community! Before you go:

--

--

Engineering Manager | Full-Stack Architect | Team/Tech Lead with a passion for frontend, backend and cloud | AWS Community Builder