Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Utilisation d'Aurora Serverless v2 avec AWS AppSync
Connectez votre API GraphQL aux bases de données Aurora Serverless à l'aide de. AWS AppSync Cette intégration vous permet d'exécuter des instructions SQL via des requêtes GraphQL, des mutations et des abonnements, ce qui vous permet d'interagir de manière flexible avec vos données relationnelles.
Note
Ce didacticiel utilise la région US-EAST-1
.
Avantages
Intégration parfaite entre GraphQL et les bases de données relationnelles
Possibilité d'effectuer des opérations SQL via des interfaces GraphQL
Évolutivité sans serveur avec Aurora Serverless v2
Accès sécurisé aux données via AWS Secrets Manager
Protection contre l'injection de code SQL grâce au nettoyage des entrées
Fonctionnalités de requête flexibles, notamment le filtrage et les opérations de plage
Cas d'utilisation courants
Création d'applications évolutives répondant à des exigences en matière de données relationnelles
Création APIs nécessitant à la fois la flexibilité de GraphQL et les fonctionnalités de base de données SQL
Gestion des opérations de données par le biais de mutations et de requêtes GraphQL
Implémentation de modèles d'accès sécurisés aux bases
Dans ce didacticiel, vous allez apprendre ce qui suit.
Configuration d'un cluster Aurora Serverless v2
Activer la fonctionnalité de l'API de données
Création et configuration de structures de base de données
Définition de schémas GraphQL pour les opérations de base de données
Implémenter des résolveurs pour les requêtes et les mutations
Sécurisez l'accès à vos données grâce à un nettoyage approprié des entrées
Exécuter diverses opérations de base de données via les interfaces GraphQL
Rubriques
Configuration de votre cluster de bases de données
Avant d'ajouter une source de données Amazon RDS à AWS AppSync, vous devez d'abord activer une API de données sur un cluster Aurora Serverless v2 et configurer un secret à l'aide de. AWS Secrets Manager Vous pouvez créer un cluster Aurora Serverless v2 à l'aide de AWS CLI :
aws rds create-db-cluster \ --db-cluster-identifier appsync-tutorial \ --engine aurora-mysql \ --engine-version 8.0 \ --serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=1 \ --master-username USERNAME \ --master-user-password COMPLEX_PASSWORD \ --enable-http-endpoint
Cela renverra un ARN pour le cluster.
Après avoir créé le cluster, vous devez ajouter une instance Aurora Serverless v2 à l'aide de la commande suivante.
aws rds create-db-instance \ --db-cluster-identifier appsync-tutorial \ --db-instance-identifier appsync-tutorial-instance-1 \ --db-instance-class db.serverless \ --engine aurora-mysql
Note
L'activation de ces points de terminaison prend du temps. Vous pouvez vérifier leur statut dans la console Amazon RDS dans l'onglet Connectivité et sécurité du cluster. Vous pouvez également vérifier l'état de votre cluster à l'aide de la AWS CLI commande suivante.
aws rds describe-db-clusters \ --db-cluster-identifier appsync-tutorial \ --query "DBClusters[0].Status"
Vous pouvez créer un secret à l'aide de la AWS Secrets Manager console ou à l' AWS CLI
aide d'un fichier d'entrée tel que le suivant en utilisant le USERNAME
et COMPLEX_PASSWORD
de l'étape précédente.
{ "username": "USERNAME", "password": "COMPLEX_PASSWORD" }
Passez ceci en tant que paramètre à AWS CLI :
aws secretsmanager create-secret --name HttpRDSSecret --secret-string file://creds.json --region us-east-1
Cela renverra un ARN pour le secret.
Notez l'ARN de votre cluster Aurora Serverless et le code secret pour une utilisation ultérieure dans la AppSync console lors de la création d'une source de données.
Activer l'API de données
Vous pouvez activer l'API de données sur votre cluster en suivant les instructions fournies dans la documentation RDS. L'API de données doit être activée avant d'être ajoutée en tant que source de AppSync données.
Créer une base de données et une table
Une fois que vous avez activé votre API de données, vous pouvez vous assurer qu'elle fonctionne à l'aide de la aws
rds-data execute-statement
commande du AWS CLI. Cela garantira que votre cluster Aurora Serverless est correctement configuré avant de l'ajouter à votre AppSync API. Créez d'abord une base de données nommée TESTDB avec le paramètre --sql
comme suit :
aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:123456789000:cluster:http-endpoint-test" \ --schema "mysql" --secret-arn "arn:aws:secretsmanager:us-east-1:123456789000:secret:testHttp2-AmNvc1" \ --region us-east-1 --sql "create DATABASE TESTDB"
Si elle s'exécute sans erreur, ajoutez une table avec la commande create table (créer une table) :
aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:123456789000:cluster:http-endpoint-test" \ --schema "mysql" --secret-arn "arn:aws:secretsmanager:us-east-1:123456789000:secret:testHttp2-AmNvc1" \ --region us-east-1 \ --sql "create table Pets(id varchar(200), type varchar(200), price float)" --database "TESTDB"
Si tout s'est déroulé sans problème, vous pouvez passer à l'ajout du cluster en tant que source de données dans votre AppSync API.
Schéma GraphQL
Maintenant que votre API de données Aurora sans serveur est opérationnel avec une table, nous allons créer un schéma GraphQL et attacher des résolveurs pour réaliser des mutations et des abonnements. Créez une nouvelle API dans la AWS AppSync console, accédez à la page Schéma, puis entrez les informations suivantes :
type Mutation { createPet(input: CreatePetInput!): Pet updatePet(input: UpdatePetInput!): Pet deletePet(input: DeletePetInput!): Pet } input CreatePetInput { type: PetType price: Float! } input UpdatePetInput { id: ID! type: PetType price: Float! } input DeletePetInput { id: ID! } type Pet { id: ID! type: PetType price: Float } enum PetType { dog cat fish bird gecko } type Query { getPet(id: ID!): Pet listPets: [Pet] listPetsByPriceRange(min: Float, max: Float): [Pet] } schema { query: Query mutation: Mutation }
Enregistrez votre schéma et accédez à la page Data Sources (Sources de données), puis créez une nouvelle source de données. Sélectionnez une Base de données relationnelle pour le type de source de données et saisissez un nom convivial. Utilisez le nom de la base de données que vous avez créé au cours de l'étape précédente, ainsi que l'ARN de cluster que vous avez créé. Pour le rôle, vous pouvez soit AppSync créer un nouveau rôle, soit en créer un avec une politique similaire à celle ci-dessous :
Notez qu'il y a deux Déclarations dans cette stratégie auxquelles vous accordez l'accès au rôle. La première ressource est votre cluster Aurora Serverless et la seconde est votre AWS Secrets Manager ARN. Vous devrez fournir les DEUX ARNs dans la configuration de la source de AppSync données avant de cliquer sur Créer.
Transmettez-le en tant que paramètre au AWS CLI.
aws secretsmanager create-secret \ --name HttpRDSSecret \ --secret-string file://creds.json \ --region us-east-1
Cela renverra un ARN pour le secret. Prenez note de l'ARN de votre cluster Aurora Serverless et de Secret pour plus tard lors de la création d'une source de données dans la AWS AppSync console.
Construisez la structure de votre base de données
Une fois que vous avez activé votre API de données, vous pouvez vous assurer qu'elle fonctionne à l'aide de la aws
rds-data execute-statement
commande du AWS CLI. Cela garantira que votre cluster Aurora Serverless v2 est correctement configuré avant de l'ajouter à votre AWS AppSync API. Créez d'abord une base de données appelée TESTDB avec le --sql
paramètre suivant.
aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:
111122223333
:cluster:appsync-tutorial
" \ --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333
:secret:appsync-tutorial-rds-secret
" \ --region us-east-1 \ --sql "create DATABASE TESTDB"
Si cela fonctionne sans erreur, ajoutez une table avec la commande create table suivante.
aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:
111122223333
:cluster:http-endpoint-test
" \ --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333
:secret:testHttp2-AmNvc1
" \ --region us-east-1 \ --sql "create table Pets(id varchar(200), type varchar(200), price float)" \ --database "TESTDB"
Concevez votre interface API
Une fois que l'API de données Aurora Serverless v2 est opérationnelle avec une table, créez un schéma GraphQL et associez des résolveurs pour effectuer des mutations et des abonnements. Créez une nouvelle API dans la AWS AppSync console, accédez à la page Schéma de la console, puis entrez ce qui suit.
type Mutation { createPet(input: CreatePetInput!): Pet updatePet(input: UpdatePetInput!): Pet deletePet(input: DeletePetInput!): Pet } input CreatePetInput { type: PetType price: Float! } input UpdatePetInput { id: ID! type: PetType price: Float! } input DeletePetInput { id: ID! } type Pet { id: ID! type: PetType price: Float } enum PetType { dog cat fish bird gecko } type Query { getPet(id: ID!): Pet listPets: [Pet] listPetsByPriceRange(min: Float, max: Float): [Pet] } schema { query: Query mutation: Mutation }
Enregistrez votre schéma et accédez à la page Data Sources (Sources de données), puis créez une nouvelle source de données. Choisissez Base de données relationnelle pour le type de source de données et fournissez un nom convivial. Utilisez le nom de la base de données que vous avez créé au cours de l'étape précédente, ainsi que l'ARN de cluster que vous avez créé. Pour le rôle, vous pouvez soit AWS AppSync créer un nouveau rôle, soit en créer un avec une politique similaire à la suivante.
Notez qu'il y a deux Déclarations dans cette stratégie auxquelles vous accordez l'accès au rôle. La première ressource est votre cluster Aurora Serverless v2 et la seconde est votre AWS Secrets Manager ARN. Vous devrez fournir les DEUX ARNs dans la configuration de la source de AWS AppSync données avant de cliquer sur Créer.
Connectez votre API aux opérations de base de données
Maintenant que nous disposons d'un schéma GraphQL valide et d'une source de données RDS, vous pouvez associer des résolveurs aux champs GraphQL de votre schéma. Notre API proposera les fonctions suivantes :
-
créer un animal de compagnie à l'aide du champ Mutation.CreatePet
-
mettre à jour un animal de compagnie à l'aide du champ Mutation.updatePet
-
supprimer un animal de compagnie à l'aide du champ Mutation.deletePet
-
obtenir un single en utilisant le champ Query.getPet
-
tout répertorier à l'aide du champ Query.listPets
-
listez les animaux de compagnie dans une fourchette de prix à l'aide de la requête. listPetsByPriceRangechamp
Mutation.createPet
Dans l'éditeur de schéma de la AWS AppSync console, sur le côté droit, choisissez Attach Resolver forcreatePet(input:
CreatePetInput!): Pet
. Choisissez votre source de données RDS. Dans la section request mapping template (modèle de mappage de requête), ajoutez le modèle suivant :
#set($id=$utils.autoId()) { "version": "2018-05-29", "statements": [ "insert into Pets VALUES (:ID, :TYPE, :PRICE)", "select * from Pets WHERE id = :ID" ], "variableMap": { ":ID": "$ctx.args.input.id", ":TYPE": $util.toJson($ctx.args.input.type), ":PRICE": $util.toJson($ctx.args.input.price) } }
Le système exécute les instructions SQL de manière séquentielle, en fonction de l'ordre dans le tableau des instructions. Les résultats reviendront dans le même ordre. Comme il s'agit d'une mutation, vous exécuterez une instruction select après l'insertion pour récupérer les valeurs validées afin de remplir le modèle de mappage des réponses GraphQL.
Dans la section response mapping template (modèle de mappage de réponse), ajoutez le modèle suivant :
$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])
Comme les déclarations possèdent deux requêtes SQL, nous devons spécifier le deuxième résultat dans la matrice qui revient de la base de données avec : $utils.rds.toJsonString($ctx.result))[1][0])
.
Mutation.updatePet
Dans l'éditeur de schéma de la AWS AppSync console, choisissez Attach Resolver forupdatePet(input: UpdatePetInput!):
Pet
. Choisissez votre source de données RDS. Dans la section Modèle de mappage des demandes, ajoutez le modèle suivant.
{ "version": "2018-05-29", "statements": [ $util.toJson("update Pets set type=:TYPE, price=:PRICE WHERE id=:ID"), $util.toJson("select * from Pets WHERE id = :ID") ], "variableMap": { ":ID": "$ctx.args.input.id", ":TYPE": $util.toJson($ctx.args.input.type), ":PRICE": $util.toJson($ctx.args.input.price) } }
Dans la section Modèle de mappage des réponses, ajoutez le modèle suivant.
$utils.toJson($utils.rds.toJsonObject($ctx.result)[1][0])
Mutation.deletePet
Dans l'éditeur de schéma de la AWS AppSync console, choisissez Attach Resolver fordeletePet(input: DeletePetInput!):
Pet
. Choisissez votre source de données RDS. Dans la section Modèle de mappage des demandes, ajoutez le modèle suivant.
{ "version": "2018-05-29", "statements": [ $util.toJson("select * from Pets WHERE id=:ID"), $util.toJson("delete from Pets WHERE id=:ID") ], "variableMap": { ":ID": "$ctx.args.input.id" } }
Dans la section Modèle de mappage des réponses, ajoutez le modèle suivant.
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])
Query.getPet
Maintenant que les mutations sont créées pour votre schéma, connectez les trois requêtes pour montrer comment obtenir des éléments individuels, des listes et appliquer un filtrage SQL. Dans l'éditeur de schéma de la AWS AppSync console, choisissez Attach Resolver forgetPet(id:
ID!): Pet
. Choisissez votre source de données RDS. Dans la section Modèle de mappage des demandes, ajoutez le modèle suivant.
{ "version": "2018-05-29", "statements": [ $util.toJson("select * from Pets WHERE id=:ID") ], "variableMap": { ":ID": "$ctx.args.id" } }
Dans la section response mapping template (modèle de mappage de réponse), ajoutez le modèle suivant :
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0][0])
Query.listPets
Dans l'éditeur de schéma de la AWS AppSync console, sur le côté droit, choisissez Attach Resolver forgetPet(id: ID!):
Pet
. Choisissez votre source de données RDS. Dans la section Modèle de mappage des demandes, ajoutez le modèle suivant.
{ "version": "2018-05-29", "statements": [ "select * from Pets" ] }
Dans la section Modèle de mappage des réponses, ajoutez le modèle suivant.
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
Requête. listPetsByPriceRange
Dans l'éditeur de schéma de la AWS AppSync console, sur le côté droit, choisissez Attach Resolver forgetPet(id: ID!):
Pet
. Choisissez votre source de données RDS. Dans la section Modèle de mappage des demandes, ajoutez le modèle suivant.
{ "version": "2018-05-29", "statements": [ "select * from Pets where price > :MIN and price < :MAX" ], "variableMap": { ":MAX": $util.toJson($ctx.args.max), ":MIN": $util.toJson($ctx.args.min) } }
Dans la section response mapping template (modèle de mappage de réponse), ajoutez le modèle suivant :
$utils.toJson($utils.rds.toJsonObject($ctx.result)[0])
Modifiez vos données via l'API
Maintenant que vous avez configuré tous vos résolveurs avec les déclarations SQL et connecté votre API GraphQL à votre API de données Aurora sans serveur, vous pouvez commencer l'exécution de mutations et de requêtes. Dans AWS AppSync la console, choisissez l'onglet Requêtes et entrez ce qui suit pour créer un animal de compagnie :
mutation add { createPet(input : { type:fish, price:10.0 }){ id type price } }
La réponse doit contenir les id, type, et prix comme suit :
{ "data": { "createPet": { "id": "c6fedbbe-57ad-4da3-860a-ffe8d039882a", "type": "fish", "price": "10.0" } } }
Vous pouvez modifier cet élément en exécutant la mutation updatePet :
mutation update { updatePet(input : { id: ID_PLACEHOLDER, type:bird, price:50.0 }){ id type price } }
Notez que nous avons utilisé l'id qui a été précédemment renvoyé de l'opération createPet. Il s'agira d'une valeur unique pour votre enregistrement car le résolveur a exploité $util.autoId()
. Vous pouvez supprimer un enregistrement de cette façon :
mutation delete { deletePet(input : {id:ID_PLACEHOLDER}){ id type price } }
Créez quelques enregistrements avec la première mutation avec des valeurs différentes pour le prix,, puis exécutez quelques requêtes.
Récupérez vos données
Toujours dans l'onglet Requêtes de la console, utilisez l'instruction suivante pour répertorier tous les enregistrements que vous avez créés.
query allpets { listPets { id type price } }
Tirez parti du prédicat SQL WHERE contenu where price > :MIN and price <
:MAX
dans notre modèle de mappage pour Query. listPetsByPriceRangeavec la requête GraphQL suivante :
query petsByPriceRange { listPetsByPriceRange(min:1, max:11) { id type price } }
Vous devez uniquement voir des enregistrements avec un prix supérieur à $1 ou inférieur à $10. Enfin, vous pouvez effectuer des requêtes pour récupérer des enregistrements spécifiques, comme suit :
query onePet { getPet(id:ID_PLACEHOLDER){ id type price } }
Sécurisez votre accès aux données
L'injection SQL constitue une faille de sécurité dans les applications de base de données. Cela se produit lorsque des attaquants insèrent du code SQL malveillant dans les champs de saisie de l'utilisateur. Cela peut permettre un accès non autorisé aux données de la base de données. Nous vous recommandons de valider et de désinfecter soigneusement toutes les entrées utilisateur avant de les traiter afin de vous protéger contre variableMap
les attaques par injection de code SQL. Si les cartes de variables ne sont pas utilisées, il vous incombe de nettoyer les arguments de leurs opérations GraphQL. L'une des façons de s'y prendre est de fournir des étapes de validation spécifique d'entrée dans le modèle de mappage de demande avant l'exécution d'une déclaration SQL sur votre API de données. Voyons comment modifier le modèle de mappage de demande de l'exemple listPetsByPriceRange
. Au lieu de vous baser uniquement sur l'entrée utilisateur, vous pouvez effectuer les actions suivantes :
#set($validMaxPrice = $util.matches("\d{1,3}[,\\.]?(\\d{1,2})?",$ctx.args.maxPrice)) #set($validMinPrice = $util.matches("\d{1,3}[,\\.]?(\\d{1,2})?",$ctx.args.minPrice)) #if (!$validMaxPrice || !$validMinPrice) $util.error("Provided price input is not valid.") #end { "version": "2018-05-29", "statements": [ "select * from Pets where price > :MIN and price < :MAX" ], "variableMap": { ":MAX": $util.toJson($ctx.args.maxPrice), ":MIN": $util.toJson($ctx.args.minPrice) } }
Une autre façon de vous protéger contre les entrées intruses lors de l'exécution de résolveurs sur vos API de données consiste à utiliser des instructions préparées avec une procédure stockée et des entrées paramétrées. Par exemple, dans le résolveur pour listPets
définissez la procédure suivante qui exécute select comme une instruction préparée :
CREATE PROCEDURE listPets (IN type_param VARCHAR(200)) BEGIN PREPARE stmt FROM 'SELECT * FROM Pets where type=?'; SET @type = type_param; EXECUTE stmt USING @type; DEALLOCATE PREPARE stmt; END
Créez-le dans votre instance Aurora Serverless v2.
aws rds-data execute-statement --resource-arn "arn:aws:rds:us-east-1:xxxxxxxxxxxx:cluster:http-endpoint-test" \ --schema "mysql" --secret-arn "arn:aws:secretsmanager:us-east-1:xxxxxxxxxxxx:secret:httpendpoint-xxxxxx" \ --region us-east-1 --database "DB_NAME" \ --sql "CREATE PROCEDURE listPets (IN type_param VARCHAR(200)) BEGIN PREPARE stmt FROM 'SELECT * FROM Pets where type=?'; SET @type = type_param; EXECUTE stmt USING @type; DEALLOCATE PREPARE stmt; END"
Le code résolveur obtenu pour listPets est simplifié, car désormais nous appelons simplement la procédure stockée. Au minimum, toute entrée de chaîne doit avoir des guillemets simples précédés d'un caractère d'échappement.
#set ($validType = $util.isString($ctx.args.type) && !$util.isNullOrBlank($ctx.args.type)) #if (!$validType) $util.error("Input for 'type' is not valid.", "ValidationError") #end { "version": "2018-05-29", "statements": [ "CALL listPets(:type)" ] "variableMap": { ":type": $util.toJson($ctx.args.type.replace("'", "''")) } }
Utilisation de chaînes d'échappement
Utilisez des guillemets simples pour marquer le début et la fin des littéraux de chaîne dans une instruction SQL, par exemple. 'some string value'
. Pour permettre l'utilisation de valeurs de chaîne avec un ou plusieurs guillemets simples ('
) dans une chaîne, chaque valeur doit être remplacée par deux guillemets simples (''
). Par exemple, si la chaîne d'entrée est Nadia's dog
, vous l'échappez pour l'instruction SQL comme
update Pets set type='Nadia''s dog' WHERE id='1'