diff --git a/cmd/create/cognito.go b/cmd/create/cognito.go index 11b4006..b0f2dae 100644 --- a/cmd/create/cognito.go +++ b/cmd/create/cognito.go @@ -2,6 +2,7 @@ package create import ( "github.com/awslabs/eksdemo/pkg/resource" + "github.com/awslabs/eksdemo/pkg/resource/cognito/client" "github.com/awslabs/eksdemo/pkg/resource/cognito/domain" "github.com/awslabs/eksdemo/pkg/resource/cognito/userpool" "github.com/spf13/cobra" @@ -27,6 +28,7 @@ func NewCognitoCmd() *cobra.Command { func init() { cognitoResources = []func() *resource.Resource{ + client.New, domain.New, userpool.New, } diff --git a/pkg/aws/cognito_userpool.go b/pkg/aws/cognito_userpool.go index dd541ed..1c3328b 100644 --- a/pkg/aws/cognito_userpool.go +++ b/pkg/aws/cognito_userpool.go @@ -30,6 +30,27 @@ func (c *CognitoUserPoolClient) CreateUserPool(name string) (*types.UserPoolType return result.UserPool, err } +// Creates the user pool client. +// When you create a new user pool client, token revocation is automatically activated. +func (c *CognitoUserPoolClient) CreateUserPoolClient(oauthScopes, callbackUrls []string, clientName, userPoolID string) (*types.UserPoolClientType, error) { + input := cognitoidp.CreateUserPoolClientInput{ + AllowedOAuthFlows: []types.OAuthFlowType{types.OAuthFlowTypeCode}, + AllowedOAuthScopes: oauthScopes, + CallbackURLs: callbackUrls, + ClientName: aws.String(clientName), + GenerateSecret: true, + SupportedIdentityProviders: []string{"COGNITO"}, + UserPoolId: aws.String(userPoolID), + } + + result, err := c.Client.CreateUserPoolClient(context.Background(), &input) + if err != nil { + return nil, err + } + + return result.UserPoolClient, nil +} + // Creates a new domain for a user pool. func (c *CognitoUserPoolClient) CreateUserPoolDomain(domain, id string) (*cognitoidp.CreateUserPoolDomainOutput, error) { input := cognitoidp.CreateUserPoolDomainInput{ diff --git a/pkg/resource/cognito/client/app_client.go b/pkg/resource/cognito/client/app_client.go index fa3bcf9..82a1ac1 100644 --- a/pkg/resource/cognito/client/app_client.go +++ b/pkg/resource/cognito/client/app_client.go @@ -26,6 +26,8 @@ func NewWithOptions(options *Options) *resource.Resource { Getter: &Getter{}, + Manager: &Manager{}, + Options: options, } } diff --git a/pkg/resource/cognito/client/get.go b/pkg/resource/cognito/client/get.go index 1e928df..a746fca 100644 --- a/pkg/resource/cognito/client/get.go +++ b/pkg/resource/cognito/client/get.go @@ -29,7 +29,7 @@ func (g *Getter) Init() { func (g *Getter) Get(name string, output printer.Output, o resource.Options) error { options, ok := o.(*Options) if !ok { - return fmt.Errorf("internal error, unable to cast options to domain.Options") + return fmt.Errorf("internal error, unable to cast options to client.Options") } var appClient *types.UserPoolClientType diff --git a/pkg/resource/cognito/client/manager.go b/pkg/resource/cognito/client/manager.go new file mode 100644 index 0000000..ee8025a --- /dev/null +++ b/pkg/resource/cognito/client/manager.go @@ -0,0 +1,72 @@ +package client + +import ( + "fmt" + + awssdk "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/cognitoidentityprovider/types" + "github.com/awslabs/eksdemo/pkg/aws" + "github.com/awslabs/eksdemo/pkg/resource" + "github.com/spf13/cobra" +) + +type Manager struct { + DryRun bool + cognitoClient *aws.CognitoUserPoolClient +} + +func (m *Manager) Init() { + if m.cognitoClient == nil { + m.cognitoClient = aws.NewCognitoUserPoolClient() + } +} + +func (m *Manager) Create(o resource.Options) error { + options, ok := o.(*Options) + if !ok { + return fmt.Errorf("internal error, unable to cast options to client.Options") + } + + if m.DryRun { + return m.dryRun(options) + } + + fmt.Printf("Creating App Client %q for User Pool Id %q...", options.ClientName, options.UserPoolID) + appClient, err := m.cognitoClient.CreateUserPoolClient( + options.OAuthScopes, + options.CallbackUrls, + options.ClientName, + options.UserPoolID, + ) + if err != nil { + return aws.FormatError(err) + } + fmt.Printf("done\nCreated Cognito App Client Id: %s\n", awssdk.ToString(appClient.ClientId)) + + return nil +} + +func (m *Manager) Delete(_ resource.Options) error { + return fmt.Errorf("feature not supported") +} + +func (m *Manager) SetDryRun() { + m.DryRun = true +} + +func (m *Manager) Update(_ resource.Options, _ *cobra.Command) error { + return fmt.Errorf("feature not supported") +} + +func (m *Manager) dryRun(options *Options) error { + fmt.Printf("\nCognito App Client Resource Manager Dry Run:\n") + fmt.Printf("Cognito User Pool API Call %q with request parameters:\n", "CreateUserPoolClient") + fmt.Printf("AllowedOAuthFlows: %q\n", []types.OAuthFlowType{types.OAuthFlowTypeCode}) + fmt.Printf("AllowedOAuthScopes: %q\n", options.OAuthScopes) + fmt.Printf("CallbackURLs: %q\n", options.CallbackUrls) + fmt.Printf("ClientName: %q\n", options.ClientName) + fmt.Printf("GenerateSecret: %s\n", "true") + fmt.Printf("SupportedIdentityProviders: %q\n", []string{"COGNITO"}) + fmt.Printf("UserPoolId: %q\n", options.UserPoolID) + return nil +} diff --git a/pkg/resource/cognito/client/options.go b/pkg/resource/cognito/client/options.go index e24798d..e13e7e1 100644 --- a/pkg/resource/cognito/client/options.go +++ b/pkg/resource/cognito/client/options.go @@ -13,16 +13,16 @@ import ( type Options struct { resource.CommonOptions - AppClientID string + ClientName string UserPoolID string UserPoolName string - // Create, Delete - ClientName string - // Create - OAuthScopes []string CallbackUrls []string + OAuthScopes []string + + // Get + AppClientID string } func NewOptions() (options *Options, createFlags, deleteFlags, getFlags cmd.Flags) { @@ -72,8 +72,25 @@ func NewOptions() (options *Options, createFlags, deleteFlags, getFlags cmd.Flag }, } - createFlags = commonFlags + createFlags = append(commonFlags, + &cmd.StringSliceFlag{ + CommandFlag: cmd.CommandFlag{ + Name: "callback-urls", + Description: "allowed redirect (callback) urls", + }, + Option: &options.CallbackUrls, + }, + &cmd.StringSliceFlag{ + CommandFlag: cmd.CommandFlag{ + Name: "oauth-scopes", + Description: "supported oauth scopes", + }, + Option: &options.OAuthScopes, + }, + ) + deleteFlags = commonFlags + getFlags = append(commonFlags, &cmd.StringFlag{ CommandFlag: cmd.CommandFlag{