Segui le istruzioni dettagliate riportate di seguito per creare il tuo back-end serverless. Fai clic sul numero di ciascuna fase per espandere la sezione.

  • Fase 1. Creazione di una policy IAM per un ruolo IAM personalizzato.

    Per concedere le autorizzazioni a gestire le richieste back-end per il tuo sito Web, puoi creare una policy IAM personalizzata che conceda tali autorizzazioni per i seguenti servizi 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
    • Gateway API
      • Sts:AssumeRole
    • CloudWatch
      • *

    Completa i seguenti passaggi per creare una policy IAM personalizzata.

     1. Apri la console IAM su https://console.aws.amazon.com/iam/

     2. Nel riquadro di navigazione, seleziona Policies (Policy).

     3. Se è la prima volta che apri Policies (Policy), si aprirà la pagina di benvenuto alle policy gestite. Scegli Get Started (Inizia subito).

     4. Scegli Create policy (Crea policy).

     5. Scegli la scheda JSON.

     6. Copia e incolla la seguente policy JSON nel campo del documento della policy.

    {
        "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. Sostituisci <REGION-CODE> con il valore corrispondente alla regione AWS in cui distribuirai il portale per l'onboarding delle applicazioni. Il valore deve contenere solo lettere minuscole. Per visualizzare l'elenco dei codici delle regioni AWS per AppStream 2.0, vai alla colonna Region (Regione) nella tabella degli endpoint Amazon AppStream 2.0, all'interno della documentazione generale AWS. Sostituisci <AWS-ACCOUNT-ID> con il tuo ID account AWS.

     8. Quando avrai finito, scegli Review policy (Verifica policy).

     9. Accanto a Name (Nome), digita questo nome per la tua nuova policy: examplecorp_eao_policy.

     10. Scegli Create policy (Crea policy).

  • Fase 2. Creazione di un ruolo IAM collegato al servizio che consenta alle funzioni Lambda di chiamare i servizi AWS.

    Lambda necessita di un ruolo IAM collegato al servizio per consentire al servizio di accedere per tuo conto alle risorse presenti in altri servizi. Completa i seguenti passaggi per creare un ruolo IAM collegato al servizio e allega la policy che hai creato a quel ruolo.

       1. Apri la console IAM su https://console.aws.amazon.com/iam/

       2. Nel pannello di navigazione, sotto Roles (Ruoli), scegli Create role (Crea ruolo).

       3. Sotto Select type of trusted entity (Seleziona il tipo di entità attendibile), mantieni la selezione di AWS service (Servizio AWS).

       4. Scegli Lambda e quindi Next: Permissions (Successivo: Autorizzazioni).

       5. Nella casella di ricerca Filter policies (Filtra policy), digita examplecorp_eao_policy. Quando vedrai la policy nell'elenco, seleziona la casella accanto al nome della policy.

       6. Seleziona Next: Tags (Successivo: Tag). Anche se è possibile specificare un tag per la policy, non è obbligatorio farlo.

       7. Seleziona Next: Review (Successivo: Verifica).

       8. Accanto a Role Name (Nome Ruolo), digita examplecorp_eao_role.

       9. Scegli Create Role (Crea ruolo).

       10. Nella casella di ricerca, digita examplecorp_eao_role. Quando vedrai il ruolo nell'elenco, seleziona il nome del ruolo.

       11. In alto nella pagina Summary (Riepilogo), viene mostrato l'ARN del ruolo. Prendi nota dell'ARN. Ti servirà nelle fasi successive del progetto.

       12. Vai alla scheda Trust relationships (Relazioni di attendibilità) e scegli Edit trust relationship (Modifica relazione di attendibilità).

       13. Sotto Policy Document (Documento Policy), configura la policy per la relazione di attendibilità in modo che includa l'azione sts:AssumeRole per le entità di servizio lambda.amazonaws.com, states.amazonaws.com e apigateway.amazonaws.com. Il formato dovrebbe essere il seguente:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "",
          "Effect": "Allow",
          "Principal": {
            "Service": [
              "lambda.amazonaws.com",
              “states.amazonaws.com”,
              "apigateway.amazonaws.com"
            ]
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }

    14. Quando avrai finito, fai clic su Update Trust Policy (Aggiorna policy di attendibilità) per salvare le modifiche.  

  • Fase 3. Creazione e configurazione di sei funzioni Lambda.

    Completa i seguenti passaggi per creare sei funzioni Lambda.

       1. Apri la console Lambda su https://console.aws.amazon.com/lambda/

       2. Scegli una delle seguenti operazioni:

          • Se non hai ancora creato funzioni Lambda vedrai una pagina di presentazione. Sotto Getting Started (Nozioni di base), scegli Create a function (Crea funzione).

          • Se hai già creato una funzione Lambda, nell'angolo in alto a destra della pagina Functions (Funzioni) scegli Create function (Crea funzione).

       3. Nella pagina Create function (Crea funzione), mantieni selezionato Author from scratch (Crea da zero)

       4. Per la sezione Basic information (Informazioni di base) segui queste istruzioni:

          • Sotto a Name (Nome), digita examplecorp_eao_createimagebuilder.

          • Per Runtime, scegli Python 3.7.

       5. Sotto Permissions (Autorizzazioni), scegli l'icona accanto a Choose or create an execution role (Scegli o crea un ruolo di esecuzione). Quindi, procedi come segue:

          • Per Execution role (Ruolo di esecuzione), scegli Use an existing role (Utilizza un ruolo esistente).

          • Per Existing role (Ruolo esistente), scegli examplecorp_eao_role dall'elenco.

       6. Fai clic su Create function (Crea funzione).

       7. Nella sezione Function code (Codice della funzione), nella scheda lambda_function verrà mostrato un codice segnaposto. Elimina il codice segnaposto, poi copia e incolla il seguente codice nella scheda:

    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. Salva la funzione. Questa funzione crea un image builder di AppStream 2.0.

       9. Ripeti i passaggi dal numero 2 al numero 8 per ciascuna delle seguenti funzioni Lambda.
           Nota: nel passaggio 7, incolla il codice della funzione Lambda corretta.

    Funzione Lambda 2: ottieni lo stato di image builder e flotta AppStream 2.0

    Quando crei questa funzione, assegnale il nome 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
    

    Funzione Lambda 3: invia un URL di streaming

    Quando crei questa funzione, assegnale il nome examplecorp_eao_sendstreamingurl.

    Nota: prima di salvare questa funzione, cerca <REGION-CODE> e sostituiscilo con il codice corrispondente alla regione AWS in cui hai configurato SES. Continua cercando Source='noreply@example.com' e sostituendo il valore con l'indirizzo e-mail che hai verificato in SES nel modulo precedente 

    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
    

    Funzione Lambda 4: ottieni il nome dell'immagine AppStream 2.0

    Quando crei questa funzione, assegnale il nome 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
    

    Funzione Lambda 5: crea una flotta e uno stack AppStream, e associa la flotta a uno stack

    Quando crei questa funzione, assegnale il nome 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
    

    Funzione Lambda 6: interrompi flotta e image builder AppStream 2.0

    Quando crei questa funzione, assegnale il nome 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