Siga las instrucciones paso a paso que se indican a continuación para crear su backend sin servidor. Haga clic en cada uno de los números de paso para ampliar la sección correspondiente.
-
Paso 1. Crear una política de IAM para un rol de IAM personalizado.
Para obtener permisos para administrar las solicitudes de backend de su sitio web, cree una política de IAM personalizada que otorgue permisos para los siguientes servicios de AWS:
- Step Functions
- StartExecution (stateMachine:examplecorp_eao)
- Sts:AssumeRole
- Lambda
- function:examplecorp_eao_createfleet
- function:examplecorp_eao_createimagebuilder
- function:examplecorp_eao_getimagename
- function:examplecorp_eao_getstatus
- function:examplecorp_eao_sendstreamingurl
- function:examplecorp_eao_stopresources
- Sts:AssumeRole
- AppStream 2.0
- AssociateFleet (Fleet/*)
- CreateFleet (Fleet/*)
- CreateImageBuilder (Image-Builder/*)
- CreateImageBuilderStreamingURL (Image-Builder/*)
- CreateStack (Stack/*)
- CreateStreamingURL (Fleet/*)
- DescribeFleets (Fleet/*)
- DescribeImageBuilders (Image-Builder/*)
- DescribeImages (Image/*)
- StartFleet (Fleet/*)
- StartImageBuilder (Image-Builder/*)
- StopFleet (Fleet/*)
- StopImageBuilder (Image-Builder/*)
- SES
- SendEmail
- API Gateway
- Sts:AssumeRole
- CloudWatch
- *
Siga los pasos que se describen a continuación para crear una política de IAM personalizada.
1. Abra la consola de IAM en https://console.aws.amazon.com/iam/
2. En el panel de navegación, elija Políticas.
3. Si es su primera vez eligiendo Políticas, aparece la página Bienvenido a las políticas administradas. Elija Introducción.
4. Elija Crear política.
5. Seleccione la pestaña JSON.
6. Copie y pegue la siguiente política JSON en el campo del documento de política.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "lambda:InvokeFunction", "appstream:DescribeImages", "appstream:StartFleet", "appstream:StopImageBuilder", "appstream:CreateStack", "appstream:CreateImageBuilderStreamingURL", "appstream:AssociateFleet", "appstream:DescribeImageBuilders", "appstream:StopFleet", "appstream:CreateImageBuilder", "appstream:CreateFleet", "appstream:DescribeFleets", "states:StartExecution", "appstream:StartImageBuilder", "appstream:CreateStreamingURL" ], "Resource": [ "arn:aws:appstream:*:*:fleet/*", "arn:aws:appstream:*:*:image/*", "arn:aws:appstream:*:*:stack/*", "arn:aws:appstream:*:*:image-builder/*", "arn:aws:states:<REGION-CODE>:<AWS-ACCOUNT-ID>:stateMachine:examplecorp_eao", "arn:aws:lambda:<REGION-CODE>:<AWS-ACCOUNT-ID>:function:examplecorp_eao_sendstreamingurl", "arn:aws:lambda:<REGION-CODE>:<AWS-ACCOUNT-ID>:function:examplecorp_eao_createimagebuilder", "arn:aws:lambda:<REGION-CODE>:<AWS-ACCOUNT-ID>:function:examplecorp_eao_getstatus", "arn:aws:lambda:<REGION-CODE>:<AWS-ACCOUNT-ID>:function:examplecorp_eao_getimagename", "arn:aws:lambda:<REGION-CODE>:<AWS-ACCOUNT-ID>:function:examplecorp_eao_createfleet", "arn:aws:lambda:<REGION-CODE>:<AWS-ACCOUNT-ID>:function:examplecorp_eao_stopresources" ] }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": [ "ses:SendEmail", "logs:CreateLogStream", "cloudwatch:*", "logs:CreateLogGroup", "logs:PutLogEvents" ], "Resource": "*" } ] }
7. Sustituya el <REGION-CODE> con el valor que corresponde a la región de AWS donde implementa el portal de incorporación de la aplicación. El valor debe estar en minúsculas. Para obtener una lista de los código de la región de AWS para AppStream 2.0, consulte la columna Región en la tabla de puntos de enlace de Amazon AppStream 2.0 de la Referencia general de AWS. Sustituya <AWS-ACCOUNT-ID> con su ID de cuenta de AWS.
8. Cuando termine, elija Revisar la política.
9. En Nombre, escriba el siguiente nombre para su nueva política: examplecorp_eao_policy.
10. Elija Crear política.
- Step Functions
-
Paso 2. Cree un rol vinculado con el servicio de IAM que permita que las funciones de Lambda llamen a los servicios de AWS.
Lambda requiere un rol vinculado con el servicio de IAM para que el servicio pueda acceder a los recursos de otros servicios en su nombre. Realice los siguientes pasos para crear un rol vinculado con el servicio de IAM y adjunte la política que creó para este rol.
1. Abra la consola de IAM en https://console.aws.amazon.com/iam/
2. En el panel de navegación, en Roles, elija Crear rol.
3. Para Seleccionar el tipo de entidad de confianza, mantenga el servicio de AWS seleccionado.
4. Elija Lambda, y luego elija Siguiente: Permisos.
5. En el cuadro de búsqueda Filtrar políticas, escriba examplecorp_eao_policy. Cuando aparece la política en la lista, seleccione el cuadro de verificación que está junto al nombre de la política.
6. Elija Siguiente: Etiquetas. Si bien puede especificar una etiqueta para la política, no se requiere una etiqueta.
7. Elija Siguiente: Revisión.
8. En Nombre del rol, escriba examplecorp_eao_role.
9. Elija Crear rol.
10. En el cuadro de búsqueda, escriba examplecorp_eao_role. Cuando aparece el rol en la lista, seleccione el nombre del rol.
11. En la parte superior de la página Resumen, aparece el ARN del rol. Tome nota de este ARN. Este ARN se necesita más adelante en el proyecto.
12. Elija la pestaña Relaciones de confianza y luego elija Editar las relaciones de confianza.
13. Bajo Documento de la política, configure la política de relación de confianza para incluir la acción sts:AssumeRole para los principales servicios lambda.amazonaws.com, states.amazonaws.com y apigateway.amazonaws.com. El formato debería ser el siguiente:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com", “states.amazonaws.com”, "apigateway.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }
14. Cuando termine, elija Actualizar política de confianza para guardar sus cambios.
-
Paso 3. Crear y configurar seis funciones de Lambda.
Siga los pasos que se describen a continuación para crear seis funciones de Lambda.
1. Abra la consola de Lambda en https://console.aws.amazon.com/lambda/
2. Aplique alguna de las siguientes acciones:
• Si no ha creado ninguna función de Lambda, aparece una página de Introducción. En Introducción, elija Crear una función.
• Si ya ha creado una función de Lambda, en la esquina superior derecha de la página Funciones, elija Crear función.
3. En la página Crear función, guarde el Autor desde cero seleccionado
4. En Información básica, haga lo siguiente:
• Para Nombre, escriba examplecorp_eao_createimagebuilder.
• Para Tiempo de ejecución, elija Python 3.7.
5. En Permisos, elija el ícono junto a Elegir o crear un rol de ejecución. Luego, haga lo siguiente:
• Para Rol de ejecución, elija Usar un rol existente.
• Para Rol existente, elija examplecorp_eao_role de la lista.
6. Haga clic en Crear función.
7. En la sección Código de función, de la pestaña lambda_function, aparece el código de marcador de posición. Borre el código de marcador de posición, y copie y pegue el siguiente código en la pestaña:
from __future__ import print_function import json import boto3 appstream = boto3.client('appstream') def lambda_handler(event, context): # Log the received event print("Received event: " + json.dumps(event, indent=2)) # Get variables from web form strIBName = event['ib_name'] strIBARN = event['ib_arn'] strInstType = event['instance_type'] strSubnetId = event['subnet1id'] strSecurityGroups = event['securitygroups'] strUserEmail = event['email'] strUserName = event['user_name'] strUserEmail = strUserEmail.strip() strUserName= strUserName.strip() try: response = appstream.create_image_builder( Name=strIBName, ImageArn=strIBARN, VpcConfig={ 'SubnetIds':[ strSubnetId ], 'SecurityGroupIds':[ strSecurityGroups ] }, InstanceType=strInstType) print("Started: " + strIBName) return 1 except Exception as e: print(e) message = 'Error creating image builder' print(message)
8. Guarde la función. Esta función crea un creador de imágenes de AppStream 2.0.
9. Repita los pasos del 2 al 8 por cada una de las siguientes funciones de Lambda.
Nota: En el paso 7, pegue el código de la función de Lambda adecuada.Función de Lambda 2: Obtenga el estado del creador de imágenes y flota de AppStream 2.0
Cuando cree esta función, nómbrela examplecorp_eao_getstatus.
from __future__ import print_function import json import boto3 print('Loading function') appstream = boto3.client('appstream') def Status_to_Return(received_state): switcher = { "PENDING": 0, "RUNNING": 1, "SNAPSHOTTING": 2, "STOPPED": 3, "STOPPING": 4, "STARTING": 5 } return switcher.get(received_state, -1) def lambda_handler(event, context): # Log the received event print("Received event: " + json.dumps(event, indent=2)) # Get names to query against strIBName = event['ib_name'] strFleetName = event['fleet_name'] strType = event['type'] try: #Fleet status check if strType == 2: print ("Type is Fleet") AS2state = appstream.describe_fleets(Names=[strFleetName]) Status = AS2state['Fleets'][0]['State'] print ("State: " + Status) #Image Builder status check elif strType == 1: print ("Type is ImageBuilder") AS2state = appstream.describe_image_builders(Names=[strIBName]) Status = AS2state['ImageBuilders'][0]['State'] print ("State: " + Status) return Status_to_Return(Status) except Exception as e: print(e) print("Error getting status") return -1
Función de Lambda 3: Envíe un URL de streaming
Cuando cree esta función, nómbrela examplecorp_eao_sendstreamingurl.
Nota: Antes de guardar esta función, busque <REGION-CODE> y sustitúyalo por el código de región que corresponde a la región de AWS en la que configuró SES. Luego, busque Source='noreply@example.com' y cambie este valor por la dirección de correo electrónico que verificó en SES en el módulo anterior
from __future__ import print_function import json import boto3 print('Loading function') appstream = boto3.client('appstream') ses = boto3.client('ses',region_name=<REGION-CODE>) def lambda_handler(event, context): # Log the received event print("Received event: " + json.dumps(event, indent=2)) # Get resource names strUserName = event['user_name'] strUserName = strUserName.strip() strEmail = event['email'] strEmail = strEmail.strip() strIBName = event['ib_name'] strFleetName = event['fleet_name'] strStackName = event['stack_name'] strType = event['type'] try: #Create Fleet Streaming URL if strType == 2: print ("Type is Fleet") mailBody = "Your fleet is now created and ready for verification. Please use the connect link below to connect to the instance." url = appstream.create_streaming_url( StackName=strStackName, FleetName=strFleetName, UserId=strUserName, Validity=604800 ) #Create Image Builder Streaming URL elif strType == 1: print ("Type is ImageBuilder") mailBody = "If this is your first time installing your application with AppStream2.0, you can check the getting started guide below for assistance. Otherwise, please click the connect link below to get started." url = appstream.create_image_builder_streaming_url( Name=strIBName, Validity=604800 ) strStreamingURL = url['StreamingURL'] print("Streaming URL: " + strStreamingURL) #Send Streaming URL in E-mail via SES ses.send_email( Source='noreply@example.com', Destination={ 'ToAddresses': [strEmail], }, Message={ 'Body': { 'Html': { 'Charset': 'UTF-8', 'Data': '<html><head><title>Example Corp</title></head><body bgcolor="#e0e0e0">' + strUserName + ',<p>Thank you for trying out the Example Corp <strong>Enterprise Application Onboarding</strong> demo. ' + mailBody + '</p><p><a href=" ' + strStreamingURL + ' ">Connect</a></p><a href="https://d1.awsstatic.com/product-marketing/AppStream2.0/Amazon%20AppStream%202.0%20Getting%20Started%20Guide%20April%202018.pdf">Getting Started Guide</a></body></html>', }, }, 'Subject': { 'Charset': 'UTF-8', 'Data': 'Example Corp Enterprise Application Onboarding for ' + strUserName }, } ) return 1 except Exception as e: print(e) print("Error getting streaming URL") return -1
Función de Lambda 4: Obtenga el nombre de la imagen de AppStream 2.0
Cuando cree esta función, nómbrela examplecorp_eao_getimagename.
from __future__ import print_function import json import boto3 import datetime print('Loading function') appstream = boto3.client('appstream') def lambda_handler(event, context): # Log the received event print("Received event: " + json.dumps(event, indent=2)) # Get names to query against strIBName = event['ib_name'] try: ImagesCMD = appstream.describe_images(Type='PRIVATE') Images = ImagesCMD['Images'] for Image in Images: if Image.get('ImageBuilderName','') == strIBName: ImageTime = Image['CreatedTime'] now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc) howold = now - ImageTime HowOldSec = howold.total_seconds() if HowOldSec < 3600: imagename = Image['Name'] return (imagename) except Exception as e: print(e) print("Error getting Image Name") return -1
Función de Lambda 5: Cree una flota y una pila de AppStream, y asocie la flota con una pila
Cuando cree esta función, nómbrela examplecorp_eao_createfleet.
from __future__ import print_function import json import boto3 print('Loading function') appstream = boto3.client('appstream') def lambda_handler(event, context): # Log the received event print("Received event: " + json.dumps(event, indent=2)) strFleetName = event['fleet_name'] strStackName = event['stack_name'] strImageName = event['imagename'] strInstType = event['instance_type'] strSubnet1Id = event['subnet1id'] strSubnet2Id = event['subnet2id'] strSecurityGroups = event['securitygroups'] try: #Create AppStream fleet fleet = appstream.create_fleet( Name=strFleetName, ImageName=strImageName, ComputeCapacity={ 'DesiredInstances': 1 }, VpcConfig={ 'SubnetIds':[ strSubnet1Id, strSubnet2Id ], 'SecurityGroupIds':[ strSecurityGroups ] }, InstanceType=strInstType) #Create AppStream stack stack = appstream.create_stack( Name=strStackName, StorageConnectors=[ { 'ConnectorType': 'HOMEFOLDERS' }, ], UserSettings=[ { 'Action': 'CLIPBOARD_COPY_FROM_LOCAL_DEVICE', 'Permission': 'ENABLED' }, ], ApplicationSettings={ 'Enabled': False } ) #Associate Stack to Fleet associate = appstream.associate_fleet( FleetName=strFleetName, StackName=strStackName ) startfleet = appstream.start_fleet( Name=strFleetName ) return 2 except Exception as e: print(e) print("Error creating fleet") return -1
Función de Lambda 6: Detenga la flota y el creador de imágenes de AppStream 2.0
Cuando cree esta función, nómbrela examplecorp_eao_stopresources.
from __future__ import print_function import json import boto3 print('Loading function') appstream = boto3.client('appstream') def Status_to_Return(received_state): switcher = { "PENDING": 0, "RUNNING": 1, "SNAPSHOTTING": 2, "STOPPED": 3, "STOPPING": 4 } return switcher.get(received_state, -1) def lambda_handler(event, context): # Log the received event print("Received event: " + json.dumps(event, indent=2)) # Get names to query against strIBName = event['ib_name'] strFleetName = event['fleet_name'] strType = event['type'] try: #Fleet status check if strType == 2: print ("Type is Fleet") AS2state = appstream.describe_fleets(Names=[strFleetName]) Status = AS2state['Fleets'][0]['State'] State = Status_to_Return(Status) if State < 3: print (strFleetName + " is " + Status + " attempting to stop") AS2stop = appstream.stop_fleet(Name=strFleetName) print ("State: " + Status) #Image Builder status check elif strType == 1: print ("Type is ImageBuilder") AS2state = appstream.describe_image_builders(Names=[strIBName]) Status = response['ImageBuilders'][0]['State'] State = Status_to_Return(Status) if State < 3: print (strIBName + " is " + Status + " attempting to stop") AS2stop = appstream.stop_image_builder(Names=[strIBName]) print ("State: " + Status) return Status_to_Return(Status) except Exception as e: print(e) print("Error stopping services") return -1