AWS 문서 예제 리포지토리에서 더 많은 SDK
기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.
를 사용하여 Lambda 함수를 사용하여 알려진 Amazon Cognito 사용자 자동 확인 AWS SDK
다음 코드 예제는 Lambda 함수를 사용하여 알려진 Amazon Cognito 사용자를 자동으로 확인하는 방법을 보여줍니다.
PreSignUp
트리거에 대해 Lambda 함수를 호출하도록 사용자 풀을 구성합니다.Amazon Cognito를 사용하여 사용자 가입시키기
Lambda 함수는 DynamoDB 테이블을 스캔하고 알려진 사용자를 자동으로 확인합니다.
새 사용자로 로그인한 다음 리소스를 정리합니다.
- Go
-
- SDK Go V2용
-
참고
에 대한 자세한 내용은 를 참조하세요 GitHub. AWS 코드 예시 리포지토리
에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요. 명령 프롬프트에서 대화형 시나리오를 실행합니다.
// AutoConfirm separates the steps of this scenario into individual functions so that // they are simpler to read and understand. type AutoConfirm struct { helper IScenarioHelper questioner demotools.IQuestioner resources Resources cognitoActor *actions.CognitoActions } // NewAutoConfirm constructs a new auto confirm runner. func NewAutoConfirm(sdkConfig aws.Config, questioner demotools.IQuestioner, helper IScenarioHelper) AutoConfirm { scenario := AutoConfirm{ helper: helper, questioner: questioner, resources: Resources{}, cognitoActor: &actions.CognitoActions{CognitoClient: cognitoidentityprovider.NewFromConfig(sdkConfig)}, } scenario.resources.init(scenario.cognitoActor, questioner) return scenario } // AddPreSignUpTrigger adds a Lambda handler as an invocation target for the PreSignUp trigger. func (runner *AutoConfirm) AddPreSignUpTrigger(userPoolId string, functionArn string) { log.Printf("Let's add a Lambda function to handle the PreSignUp trigger from Cognito.\n" + "This trigger happens when a user signs up, and lets your function take action before the main Cognito\n" + "sign up processing occurs.\n") err := runner.cognitoActor.UpdateTriggers( userPoolId, actions.TriggerInfo{Trigger: actions.PreSignUp, HandlerArn: aws.String(functionArn)}) if err != nil { panic(err) } log.Printf("Lambda function %v added to user pool %v to handle the PreSignUp trigger.\n", functionArn, userPoolId) } // SignUpUser signs up a user from the known user table with a password you specify. func (runner *AutoConfirm) SignUpUser(clientId string, usersTable string) (string, string) { log.Println("Let's sign up a user to your Cognito user pool. When the user's email matches an email in the\n" + "DynamoDB known users table, it is automatically verified and the user is confirmed.") knownUsers, err := runner.helper.GetKnownUsers(usersTable) if err != nil { panic(err) } userChoice := runner.questioner.AskChoice("Which user do you want to use?\n", knownUsers.UserNameList()) user := knownUsers.Users[userChoice] var signedUp bool var userConfirmed bool password := runner.questioner.AskPassword("Enter a password that has at least eight characters, uppercase, lowercase, numbers and symbols.\n"+ "(the password will not display as you type):", 8) for !signedUp { log.Printf("Signing up user '%v' with email '%v' to Cognito.\n", user.UserName, user.UserEmail) userConfirmed, err = runner.cognitoActor.SignUp(clientId, user.UserName, password, user.UserEmail) if err != nil { var invalidPassword *types.InvalidPasswordException if errors.As(err, &invalidPassword) { password = runner.questioner.AskPassword("Enter another password:", 8) } else { panic(err) } } else { signedUp = true } } log.Printf("User %v signed up, confirmed = %v.\n", user.UserName, userConfirmed) log.Println(strings.Repeat("-", 88)) return user.UserName, password } // SignInUser signs in a user. func (runner *AutoConfirm) SignInUser(clientId string, userName string, password string) string { runner.questioner.Ask("Press Enter when you're ready to continue.") log.Printf("Let's sign in as %v...\n", userName) authResult, err := runner.cognitoActor.SignIn(clientId, userName, password) if err != nil { panic(err) } log.Printf("Successfully signed in. Your access token starts with: %v...\n", (*authResult.AccessToken)[:10]) log.Println(strings.Repeat("-", 88)) return *authResult.AccessToken } // Run runs the scenario. func (runner *AutoConfirm) Run(stackName string) { defer func() { if r := recover(); r != nil { log.Println("Something went wrong with the demo.") runner.resources.Cleanup() } }() log.Println(strings.Repeat("-", 88)) log.Printf("Welcome\n") log.Println(strings.Repeat("-", 88)) stackOutputs, err := runner.helper.GetStackOutputs(stackName) if err != nil { panic(err) } runner.resources.userPoolId = stackOutputs["UserPoolId"] runner.helper.PopulateUserTable(stackOutputs["TableName"]) runner.AddPreSignUpTrigger(stackOutputs["UserPoolId"], stackOutputs["AutoConfirmFunctionArn"]) runner.resources.triggers = append(runner.resources.triggers, actions.PreSignUp) userName, password := runner.SignUpUser(stackOutputs["UserPoolClientId"], stackOutputs["TableName"]) runner.helper.ListRecentLogEvents(stackOutputs["AutoConfirmFunction"]) runner.resources.userAccessTokens = append(runner.resources.userAccessTokens, runner.SignInUser(stackOutputs["UserPoolClientId"], userName, password)) runner.resources.Cleanup() log.Println(strings.Repeat("-", 88)) log.Println("Thanks for watching!") log.Println(strings.Repeat("-", 88)) }
Lambda 함수를 사용하여
PreSignUp
트리거를 처리합니다.const TABLE_NAME = "TABLE_NAME" // UserInfo defines structured user data that can be marshalled to a DynamoDB format. type UserInfo struct { UserName string `dynamodbav:"UserName"` UserEmail string `dynamodbav:"UserEmail"` } // GetKey marshals the user email value to a DynamoDB key format. func (user UserInfo) GetKey() map[string]dynamodbtypes.AttributeValue { userEmail, err := attributevalue.Marshal(user.UserEmail) if err != nil { panic(err) } return map[string]dynamodbtypes.AttributeValue{"UserEmail": userEmail} } type handler struct { dynamoClient *dynamodb.Client } // HandleRequest handles the PreSignUp event by looking up a user in an Amazon DynamoDB table and // specifying whether they should be confirmed and verified. func (h *handler) HandleRequest(ctx context.Context, event events.CognitoEventUserPoolsPreSignup) (events.CognitoEventUserPoolsPreSignup, error) { log.Printf("Received presignup from %v for user '%v'", event.TriggerSource, event.UserName) if event.TriggerSource != "PreSignUp_SignUp" { // Other trigger sources, such as PreSignUp_AdminInitiateAuth, ignore the response from this handler. return event, nil } tableName := os.Getenv(TABLE_NAME) user := UserInfo{ UserEmail: event.Request.UserAttributes["email"], } log.Printf("Looking up email %v in table %v.\n", user.UserEmail, tableName) output, err := h.dynamoClient.GetItem(ctx, &dynamodb.GetItemInput{ Key: user.GetKey(), TableName: aws.String(tableName), }) if err != nil { log.Printf("Error looking up email %v.\n", user.UserEmail) return event, err } if output.Item == nil { log.Printf("Email %v not found. Email verification is required.\n", user.UserEmail) return event, err } err = attributevalue.UnmarshalMap(output.Item, &user) if err != nil { log.Printf("Couldn't unmarshal DynamoDB item. Here's why: %v\n", err) return event, err } if user.UserName != event.UserName { log.Printf("UserEmail %v found, but stored UserName '%v' does not match supplied UserName '%v'. Verification is required.\n", user.UserEmail, user.UserName, event.UserName) } else { log.Printf("UserEmail %v found with matching UserName %v. User is confirmed.\n", user.UserEmail, user.UserName) event.Response.AutoConfirmUser = true event.Response.AutoVerifyEmail = true } return event, err } func main() { sdkConfig, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Panicln(err) } h := handler{ dynamoClient: dynamodb.NewFromConfig(sdkConfig), } lambda.Start(h.HandleRequest) }
일반적인 작업을 수행하는 구조체를 생성합니다.
// IScenarioHelper defines common functions used by the workflows in this example. type IScenarioHelper interface { Pause(secs int) GetStackOutputs(stackName string) (actions.StackOutputs, error) PopulateUserTable(tableName string) GetKnownUsers(tableName string) (actions.UserList, error) AddKnownUser(tableName string, user actions.User) ListRecentLogEvents(functionName string) } // ScenarioHelper contains AWS wrapper structs used by the workflows in this example. type ScenarioHelper struct { questioner demotools.IQuestioner dynamoActor *actions.DynamoActions cfnActor *actions.CloudFormationActions cwlActor *actions.CloudWatchLogsActions isTestRun bool } // NewScenarioHelper constructs a new scenario helper. func NewScenarioHelper(sdkConfig aws.Config, questioner demotools.IQuestioner) ScenarioHelper { scenario := ScenarioHelper{ questioner: questioner, dynamoActor: &actions.DynamoActions{DynamoClient: dynamodb.NewFromConfig(sdkConfig)}, cfnActor: &actions.CloudFormationActions{CfnClient: cloudformation.NewFromConfig(sdkConfig)}, cwlActor: &actions.CloudWatchLogsActions{CwlClient: cloudwatchlogs.NewFromConfig(sdkConfig)}, } return scenario } // Pause waits for the specified number of seconds. func (helper ScenarioHelper) Pause(secs int) { if !helper.isTestRun { time.Sleep(time.Duration(secs) * time.Second) } } // GetStackOutputs gets the outputs from the specified CloudFormation stack in a structured format. func (helper ScenarioHelper) GetStackOutputs(stackName string) (actions.StackOutputs, error) { return helper.cfnActor.GetOutputs(stackName), nil } // PopulateUserTable fills the known user table with example data. func (helper ScenarioHelper) PopulateUserTable(tableName string) { log.Printf("First, let's add some users to the DynamoDB %v table we'll use for this example.\n", tableName) err := helper.dynamoActor.PopulateTable(tableName) if err != nil { panic(err) } } // GetKnownUsers gets the users from the known users table in a structured format. func (helper ScenarioHelper) GetKnownUsers(tableName string) (actions.UserList, error) { knownUsers, err := helper.dynamoActor.Scan(tableName) if err != nil { log.Printf("Couldn't get known users from table %v. Here's why: %v\n", tableName, err) } return knownUsers, err } // AddKnownUser adds a user to the known users table. func (helper ScenarioHelper) AddKnownUser(tableName string, user actions.User) { log.Printf("Adding user '%v' with email '%v' to the DynamoDB known users table...\n", user.UserName, user.UserEmail) err := helper.dynamoActor.AddUser(tableName, user) if err != nil { panic(err) } } // ListRecentLogEvents gets the most recent log stream and events for the specified Lambda function and displays them. func (helper ScenarioHelper) ListRecentLogEvents(functionName string) { log.Println("Waiting a few seconds to let Lambda write to CloudWatch Logs...") helper.Pause(10) log.Println("Okay, let's check the logs to find what's happened recently with your Lambda function.") logStream, err := helper.cwlActor.GetLatestLogStream(functionName) if err != nil { panic(err) } log.Printf("Getting some recent events from log stream %v\n", *logStream.LogStreamName) events, err := helper.cwlActor.GetLogEvents(functionName, *logStream.LogStreamName, 10) if err != nil { panic(err) } for _, event := range events { log.Printf("\t%v", *event.Message) } log.Println(strings.Repeat("-", 88)) }
Amazon Cognito 작업을 래핑하는 구조체를 생성합니다.
type CognitoActions struct { CognitoClient *cognitoidentityprovider.Client } // Trigger and TriggerInfo define typed data for updating an Amazon Cognito trigger. type Trigger int const ( PreSignUp Trigger = iota UserMigration PostAuthentication ) type TriggerInfo struct { Trigger Trigger HandlerArn *string } // UpdateTriggers adds or removes Lambda triggers for a user pool. When a trigger is specified with a `nil` value, // it is removed from the user pool. func (actor CognitoActions) UpdateTriggers(userPoolId string, triggers ...TriggerInfo) error { output, err := actor.CognitoClient.DescribeUserPool(context.TODO(), &cognitoidentityprovider.DescribeUserPoolInput{ UserPoolId: aws.String(userPoolId), }) if err != nil { log.Printf("Couldn't get info about user pool %v. Here's why: %v\n", userPoolId, err) return err } lambdaConfig := output.UserPool.LambdaConfig for _, trigger := range triggers { switch trigger.Trigger { case PreSignUp: lambdaConfig.PreSignUp = trigger.HandlerArn case UserMigration: lambdaConfig.UserMigration = trigger.HandlerArn case PostAuthentication: lambdaConfig.PostAuthentication = trigger.HandlerArn } } _, err = actor.CognitoClient.UpdateUserPool(context.TODO(), &cognitoidentityprovider.UpdateUserPoolInput{ UserPoolId: aws.String(userPoolId), LambdaConfig: lambdaConfig, }) if err != nil { log.Printf("Couldn't update user pool %v. Here's why: %v\n", userPoolId, err) } return err } // SignUp signs up a user with Amazon Cognito. func (actor CognitoActions) SignUp(clientId string, userName string, password string, userEmail string) (bool, error) { confirmed := false output, err := actor.CognitoClient.SignUp(context.TODO(), &cognitoidentityprovider.SignUpInput{ ClientId: aws.String(clientId), Password: aws.String(password), Username: aws.String(userName), UserAttributes: []types.AttributeType{ {Name: aws.String("email"), Value: aws.String(userEmail)}, }, }) if err != nil { var invalidPassword *types.InvalidPasswordException if errors.As(err, &invalidPassword) { log.Println(*invalidPassword.Message) } else { log.Printf("Couldn't sign up user %v. Here's why: %v\n", userName, err) } } else { confirmed = output.UserConfirmed } return confirmed, err } // SignIn signs in a user to Amazon Cognito using a username and password authentication flow. func (actor CognitoActions) SignIn(clientId string, userName string, password string) (*types.AuthenticationResultType, error) { var authResult *types.AuthenticationResultType output, err := actor.CognitoClient.InitiateAuth(context.TODO(), &cognitoidentityprovider.InitiateAuthInput{ AuthFlow: "USER_PASSWORD_AUTH", ClientId: aws.String(clientId), AuthParameters: map[string]string{"USERNAME": userName, "PASSWORD": password}, }) if err != nil { var resetRequired *types.PasswordResetRequiredException if errors.As(err, &resetRequired) { log.Println(*resetRequired.Message) } else { log.Printf("Couldn't sign in user %v. Here's why: %v\n", userName, err) } } else { authResult = output.AuthenticationResult } return authResult, err } // ForgotPassword starts a password recovery flow for a user. This flow typically sends a confirmation code // to the user's configured notification destination, such as email. func (actor CognitoActions) ForgotPassword(clientId string, userName string) (*types.CodeDeliveryDetailsType, error) { output, err := actor.CognitoClient.ForgotPassword(context.TODO(), &cognitoidentityprovider.ForgotPasswordInput{ ClientId: aws.String(clientId), Username: aws.String(userName), }) if err != nil { log.Printf("Couldn't start password reset for user '%v'. Here;s why: %v\n", userName, err) } return output.CodeDeliveryDetails, err } // ConfirmForgotPassword confirms a user with a confirmation code and a new password. func (actor CognitoActions) ConfirmForgotPassword(clientId string, code string, userName string, password string) error { _, err := actor.CognitoClient.ConfirmForgotPassword(context.TODO(), &cognitoidentityprovider.ConfirmForgotPasswordInput{ ClientId: aws.String(clientId), ConfirmationCode: aws.String(code), Password: aws.String(password), Username: aws.String(userName), }) if err != nil { var invalidPassword *types.InvalidPasswordException if errors.As(err, &invalidPassword) { log.Println(*invalidPassword.Message) } else { log.Printf("Couldn't confirm user %v. Here's why: %v", userName, err) } } return err } // DeleteUser removes a user from the user pool. func (actor CognitoActions) DeleteUser(userAccessToken string) error { _, err := actor.CognitoClient.DeleteUser(context.TODO(), &cognitoidentityprovider.DeleteUserInput{ AccessToken: aws.String(userAccessToken), }) if err != nil { log.Printf("Couldn't delete user. Here's why: %v\n", err) } return err } // AdminCreateUser uses administrator credentials to add a user to a user pool. This method leaves the user // in a state that requires they enter a new password next time they sign in. func (actor CognitoActions) AdminCreateUser(userPoolId string, userName string, userEmail string) error { _, err := actor.CognitoClient.AdminCreateUser(context.TODO(), &cognitoidentityprovider.AdminCreateUserInput{ UserPoolId: aws.String(userPoolId), Username: aws.String(userName), MessageAction: types.MessageActionTypeSuppress, UserAttributes: []types.AttributeType{{Name: aws.String("email"), Value: aws.String(userEmail)}}, }) if err != nil { var userExists *types.UsernameExistsException if errors.As(err, &userExists) { log.Printf("User %v already exists in the user pool.", userName) err = nil } else { log.Printf("Couldn't create user %v. Here's why: %v\n", userName, err) } } return err } // AdminSetUserPassword uses administrator credentials to set a password for a user without requiring a // temporary password. func (actor CognitoActions) AdminSetUserPassword(userPoolId string, userName string, password string) error { _, err := actor.CognitoClient.AdminSetUserPassword(context.TODO(), &cognitoidentityprovider.AdminSetUserPasswordInput{ Password: aws.String(password), UserPoolId: aws.String(userPoolId), Username: aws.String(userName), Permanent: true, }) if err != nil { var invalidPassword *types.InvalidPasswordException if errors.As(err, &invalidPassword) { log.Println(*invalidPassword.Message) } else { log.Printf("Couldn't set password for user %v. Here's why: %v\n", userName, err) } } return err }
DynamoDB 작업을 래핑하는 구조체를 생성합니다.
// DynamoActions encapsulates the Amazon Simple Notification Service (Amazon SNS) actions // used in the examples. type DynamoActions struct { DynamoClient *dynamodb.Client } // User defines structured user data. type User struct { UserName string UserEmail string LastLogin *LoginInfo `dynamodbav:",omitempty"` } // LoginInfo defines structured custom login data. type LoginInfo struct { UserPoolId string ClientId string Time string } // UserList defines a list of users. type UserList struct { Users []User } // UserNameList returns the usernames contained in a UserList as a list of strings. func (users *UserList) UserNameList() []string { names := make([]string, len(users.Users)) for i := 0; i < len(users.Users); i++ { names[i] = users.Users[i].UserName } return names } // PopulateTable adds a set of test users to the table. func (actor DynamoActions) PopulateTable(tableName string) error { var err error var item map[string]types.AttributeValue var writeReqs []types.WriteRequest for i := 1; i < 4; i++ { item, err = attributevalue.MarshalMap(User{UserName: fmt.Sprintf("test_user_%v", i), UserEmail: fmt.Sprintf("test_email_%v@example.com", i)}) if err != nil { log.Printf("Couldn't marshall user into DynamoDB format. Here's why: %v\n", err) return err } writeReqs = append(writeReqs, types.WriteRequest{PutRequest: &types.PutRequest{Item: item}}) } _, err = actor.DynamoClient.BatchWriteItem(context.TODO(), &dynamodb.BatchWriteItemInput{ RequestItems: map[string][]types.WriteRequest{tableName: writeReqs}, }) if err != nil { log.Printf("Couldn't populate table %v with users. Here's why: %v\n", tableName, err) } return err } // Scan scans the table for all items. func (actor DynamoActions) Scan(tableName string) (UserList, error) { var userList UserList output, err := actor.DynamoClient.Scan(context.TODO(), &dynamodb.ScanInput{ TableName: aws.String(tableName), }) if err != nil { log.Printf("Couldn't scan table %v for items. Here's why: %v\n", tableName, err) } else { err = attributevalue.UnmarshalListOfMaps(output.Items, &userList.Users) if err != nil { log.Printf("Couldn't unmarshal items into users. Here's why: %v\n", err) } } return userList, err } // AddUser adds a user item to a table. func (actor DynamoActions) AddUser(tableName string, user User) error { userItem, err := attributevalue.MarshalMap(user) if err != nil { log.Printf("Couldn't marshall user to item. Here's why: %v\n", err) } _, err = actor.DynamoClient.PutItem(context.TODO(), &dynamodb.PutItemInput{ Item: userItem, TableName: aws.String(tableName), }) if err != nil { log.Printf("Couldn't put item in table %v. Here's why: %v", tableName, err) } return err }
CloudWatch 로그 작업을 래핑하는 구조를 생성합니다.
type CloudWatchLogsActions struct { CwlClient *cloudwatchlogs.Client } // GetLatestLogStream gets the most recent log stream for a Lambda function. func (actor CloudWatchLogsActions) GetLatestLogStream(functionName string) (types.LogStream, error) { var logStream types.LogStream logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName) output, err := actor.CwlClient.DescribeLogStreams(context.TODO(), &cloudwatchlogs.DescribeLogStreamsInput{ Descending: aws.Bool(true), Limit: aws.Int32(1), LogGroupName: aws.String(logGroupName), OrderBy: types.OrderByLastEventTime, }) if err != nil { log.Printf("Couldn't get log streams for log group %v. Here's why: %v\n", logGroupName, err) } else { logStream = output.LogStreams[0] } return logStream, err } // GetLogEvents gets the most recent eventCount events from the specified log stream. func (actor CloudWatchLogsActions) GetLogEvents(functionName string, logStreamName string, eventCount int32) ( []types.OutputLogEvent, error) { var events []types.OutputLogEvent logGroupName := fmt.Sprintf("/aws/lambda/%s", functionName) output, err := actor.CwlClient.GetLogEvents(context.TODO(), &cloudwatchlogs.GetLogEventsInput{ LogStreamName: aws.String(logStreamName), Limit: aws.Int32(eventCount), LogGroupName: aws.String(logGroupName), }) if err != nil { log.Printf("Couldn't get log event for log stream %v. Here's why: %v\n", logStreamName, err) } else { events = output.Events } return events, err }
AWS CloudFormation 작업을 래핑하는 구조를 생성합니다.
// StackOutputs defines a map of outputs from a specific stack. type StackOutputs map[string]string type CloudFormationActions struct { CfnClient *cloudformation.Client } // GetOutputs gets the outputs from a CloudFormation stack and puts them into a structured format. func (actor CloudFormationActions) GetOutputs(stackName string) StackOutputs { output, err := actor.CfnClient.DescribeStacks(context.TODO(), &cloudformation.DescribeStacksInput{ StackName: aws.String(stackName), }) if err != nil || len(output.Stacks) == 0 { log.Panicf("Couldn't find a CloudFormation stack named %v. Here's why: %v\n", stackName, err) } stackOutputs := StackOutputs{} for _, out := range output.Stacks[0].Outputs { stackOutputs[*out.OutputKey] = *out.OutputValue } return stackOutputs }
리소스를 정리합니다.
// Resources keeps track of AWS resources created during an example and handles // cleanup when the example finishes. type Resources struct { userPoolId string userAccessTokens []string triggers []actions.Trigger cognitoActor *actions.CognitoActions questioner demotools.IQuestioner } func (resources *Resources) init(cognitoActor *actions.CognitoActions, questioner demotools.IQuestioner) { resources.userAccessTokens = []string{} resources.triggers = []actions.Trigger{} resources.cognitoActor = cognitoActor resources.questioner = questioner } // Cleanup deletes all AWS resources created during an example. func (resources *Resources) Cleanup() { defer func() { if r := recover(); r != nil { log.Printf("Something went wrong during cleanup.\n%v\n", r) log.Println("Use the AWS Management Console to remove any remaining resources \n" + "that were created for this scenario.") } }() wantDelete := resources.questioner.AskBool("Do you want to remove all of the AWS resources that were created "+ "during this demo (y/n)?", "y") if wantDelete { for _, accessToken := range resources.userAccessTokens { err := resources.cognitoActor.DeleteUser(accessToken) if err != nil { log.Println("Couldn't delete user during cleanup.") panic(err) } log.Println("Deleted user.") } triggerList := make([]actions.TriggerInfo, len(resources.triggers)) for i := 0; i < len(resources.triggers); i++ { triggerList[i] = actions.TriggerInfo{Trigger: resources.triggers[i], HandlerArn: nil} } err := resources.cognitoActor.UpdateTriggers(resources.userPoolId, triggerList...) if err != nil { log.Println("Couldn't update Cognito triggers during cleanup.") panic(err) } log.Println("Removed Cognito triggers from user pool.") } else { log.Println("Be sure to remove resources when you're done with them to avoid unexpected charges!") } }
-
API 자세한 내용은 AWS SDK for Go API 참조 의 다음 주제를 참조하세요.
-
시나리오
Lambda 함수를 사용하여 알려진 사용자를 자동으로 마이그레이션