Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 'aws_cognito_user_pool_client' resource #1803

Closed
wants to merge 0 commits into from

Conversation

@psyvision
Copy link
Contributor

@psyvision psyvision commented Oct 3, 2017

Description

The following pull request builds upon the work of @Ninir implementing Cognito User Pools (not yet merged) by adding support for Cognito User Pool Clients.

I've added some documentation on using the new resource.

Note: This doesn't provide full API support at current but does allow a client to be created and the ClientId returned.

API Documentation

Test

make testacc TEST=./aws TESTARGS='-run=TestAccAWSCognitoUserPoolClient_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSCognitoUserPoolClient_ -timeout 120m
=== RUN   TestAccAWSCognitoUserPoolClient_basic
--- PASS: TestAccAWSCognitoUserPoolClient_basic (19.11s)
PASS
ok      github.com/terraform-providers/terraform-provider-aws/aws       19.126s

Resources

resource "aws_cognito_user_pool_client" "client" {
}
@psyvision psyvision changed the title Cognito User Pool Client Add 'aws_cognito_user_pool_client' resource Oct 4, 2017
@radeksimko radeksimko modified the milestones: v1.2.0, v1.3.0 Oct 26, 2017
@radeksimko radeksimko added the size/XXL label Nov 15, 2017
@radeksimko radeksimko modified the milestones: v1.3.0, v1.4.0 Nov 15, 2017
@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Nov 15, 2017

@radeksimko do you have any pointers on how I should implement the custom user pool client attributes that belong to the user pool client?

See the AWS API reference below:
http://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AddCustomAttributes.html

These are different to the typical "attributes" that belong to resources (i.e. attributes are an entity in themselves to some extent).

I could add a further resource "aws_cognito_user_pool_client_attribute" or have them as a set on the client_pool resource I've already added, similar to ingress/egress rules on a security group...

@radeksimko
Copy link
Member

@radeksimko radeksimko commented Nov 15, 2017

We will take a look at this PR 🔜 after merging #1419 which should be either today or tomorrow, but given the tight schedule for 1.3.0 we intend to ship tomorrow I reckon we'll leave this PR for the next release.

@Ninir
Copy link
Contributor

@Ninir Ninir commented Nov 16, 2017

Hi @psyvision

User Pools have just been merged and it's all available in AWS 1.3.0!
Could you rebase your PR against master so that we can go on on this one?

Thanks!

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Nov 17, 2017

Hi @Ninir,

I saw that, I'll merge in this evening for you :)

Cheers

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Nov 17, 2017

@Ninir I got there one way or another, all merged now!

@et304383
Copy link

@et304383 et304383 commented Nov 20, 2017

So excited to see this coming in soon!

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Nov 20, 2017

@et304383 am I correct in thinking you want custom attribute support too? We need that but I'm not sure how to code it. Once @Ninir gets started on this PR I'll see what I can sort out.

@et304383
Copy link

@et304383 et304383 commented Nov 20, 2017

@psyvision that would be nice to have long term but in the short term what we need is the ability to create them and specify the refresh token validity.

We need React frontends to be able to interact with Cognito as a priority. We've resorted to adding the client creation through a python script in the short term.

@CalebMacdonaldBlack
Copy link

@CalebMacdonaldBlack CalebMacdonaldBlack commented Nov 27, 2017

@psyvision @Ninir Great to see cognito user pools! Just waiting on app clients and custom attributes before we can use it

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Nov 27, 2017

@CalebMacdonaldBlack app clients are in, I can't remember if I covered off all functionality (I think maybe so...) I don't know how to go about implementing custom attributes, otherwise I would have done so. Once @Ninir gets on to this or gives me some pointers I'll do it :)

Copy link
Member

@radeksimko radeksimko left a comment

Hi @psyvision
thanks for the PR. I left you some comments.

Regarding custom attributes I think we should model that as a separate resource, e.g. aws_cognito_user_attribute - which is outside of scope of this PR. We'll also need to find out whether/how it conflicts with existing resources.


if v, ok := d.GetOk("refresh_token_validity"); ok {
params.RefreshTokenValidity = aws.Int64(v.(int64))
}

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

I see there are some fields missing in the schema:

	AllowedOAuthFlows []*string `type:"list"`

	// Set to True if the client is allowed to follow the OAuth protocol when interacting
	// with Cognito user pools.
	AllowedOAuthFlowsUserPoolClient *bool `type:"boolean"`

	// A list of allowed OAuth scopes. Currently supported values are "phone", "email",
	// "openid", and "Cognito".
	AllowedOAuthScopes []*string `type:"list"`

	// A list of allowed callback URLs for the identity providers.
	CallbackURLs []*string `type:"list"`

	// The default redirect URI. Must be in the CallbackURLs list.
	DefaultRedirectURI *string `min:"1" type:"string"`

	// A list of allowed logout URLs for the identity providers.
	LogoutURLs []*string `type:"list"`

	// A list of provider names for the identity providers that are supported on
	// this client.
	SupportedIdentityProviders []*string `type:"list"`

Do you plan on adding those?

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

I haven't used these so I'm not sure exactly what's best / what's expected or to be able to test them for real. I can have a go though :D

This comment has been minimized.

@radeksimko

radeksimko Dec 5, 2017
Member

Yeah - I think the best we can do is to read the relevant docs and try to build a few simple examples with those fields in a test based on that. If you want to test it for real (i.e. login in the browser) then I take that as a bonus, but I'd just assume it works as long as the API accepts our request. 🤷‍♂️


"refresh_token_validity": {
Type: schema.TypeInt,
Optional: true,

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

The default validity seems to be set to 30 by the API which is why the acceptance test is failing:

=== RUN   TestAccAWSCognitoUserPoolClient_basic
--- FAIL: TestAccAWSCognitoUserPoolClient_basic (34.36s)
	testing.go:503: Step 0 error: After applying this step, the plan was not empty:

		DIFF:

		UPDATE: aws_cognito_user_pool_client.client
		  refresh_token_validity: "30" => "0"

Do you mind setting Default: 30 here too?

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

No issues with that

}

if v, ok := d.GetOk("refresh_token_validity"); ok {
params.RefreshTokenValidity = aws.Int64(v.(int64))

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

We get int, not int64 from the ResourceData, so this would cause a crash due to invalid cast. I think we'll need to change it to something like this:

params.RefreshTokenValidity = aws.Int64(int64(v.(int)))

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

I hadn't actually tested this in AWS and was just going on what VS Code was telling me so I'll take your call.

resp, err := conn.DescribeUserPoolClient(params)

if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "ResourceNotFoundException" {

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

Nitpick: this error handling here can be simplified to

if isAWSErr(err, "ResourceNotFoundException", "") {
* `name` - (Required) The name of the application client.
* `generate_secret` - (Optional) Should an application secret be generated. AWS JavaScript SDK requires this to be false.
* `user_pool_id` - (Required) The user pool the client belongs to.
* `explicit_auth_flows` - (Optional) List of authentication flows (ADMIN_NO_SRP_AUTH, CUSTOM_AUTH_FLOW_ONLY)

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

I think the list of fields here is incomplete - do you mind updating it?

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

Will do

"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

It looks like this field is updatable (at least it's present in UpdateUserPoolClientInput) - is there any reason for making it ForceNew?

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

Nope, just me not knowing what's what :)

"explicit_auth_flows": {
Type: schema.TypeList,
Optional: true,
ForceNew: false,

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

It looks like this field is updatable (at least it's present in UpdateUserPoolClientInput) - is there any reason for making it ForceNew?

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

Not sure which field this refers to? If explicit_auth_flows then it's false

This comment has been minimized.

@radeksimko

radeksimko Dec 5, 2017
Member

Ah, sorry - I missed that - so in that case it's practically correct, but it's false by default so we can just omit it.

"read_attributes": {
Type: schema.TypeList,
Optional: true,
ForceNew: false,

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

Likewise - ^

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

read_attributes is ForceNew: false but I guess the redundant code can be removed

This comment has been minimized.

@radeksimko

radeksimko Dec 5, 2017
Member

Yes, it can be removed - there's no point of having ForceNew: false anywhere as that's default. 😉

"write_attributes": {
Type: schema.TypeList,
Optional: true,
ForceNew: false,

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

Likewise - ^

This comment has been minimized.

@psyvision

psyvision Dec 4, 2017
Author Contributor

write_attributes is ForceNew: false but I guess the redundant code can be removed

This comment has been minimized.

@radeksimko

radeksimko Dec 5, 2017
Member

Correct.

"refresh_token_validity": {
Type: schema.TypeInt,
Optional: true,
ForceNew: false,

This comment has been minimized.

@radeksimko

radeksimko Dec 4, 2017
Member

Likewise - ^

This comment has been minimized.

@radeksimko

radeksimko Dec 5, 2017
Member

It's just redundant - that's all 😉

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Dec 4, 2017

@radeksimko Thank you for reviewing these. I'll go through and make some changes where required. I don't think the attributes are needed. I looked into it and they actually fall under the aws_cognito_user_pool implemented in 1.3.0 (I think) and not in the client.


if resp.UserPoolClient.ClientSecret != nil {
d.Set("client_secret", resp.UserPoolClient.ClientSecret)
}

This comment has been minimized.

@radeksimko

radeksimko Dec 5, 2017
Member

d.Set() will perform safe dereferencing (and deal with nil without crashing), so all of the above 5 checks are redundant. 😉

This comment has been minimized.

@psyvision

psyvision Dec 5, 2017
Author Contributor

Ah thanks. I've been copying code from elsewhere rather than looking into the intracacies. I'll add that to my changes. Just had to rebuild my dev VM

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Dec 5, 2017

ok @radeksimko I've covered off the items in your review I think. Just need to add in those final attributes which I'll do shortly.


d.SetId(*resp.UserPoolClient.ClientId)
d.Set("user_pool_id", *resp.UserPoolClient.UserPoolId)
d.Set("name", *resp.UserPoolClient.ClientName)

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

The two d.Set()s are IMO unnecessary unless we believe the API would return something that differs from the original query - in which case we'd probably have much bigger problem.

Type: schema.TypeString,
ValidateFunc: validation.StringInSlice([]string{
cognitoidentityprovider.AuthFlowTypeAdminNoSrpAuth,
cognitoidentityprovider.AuthFlowTypeCustomAuth,

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

I think this should be cognitoidentityprovider.ExplicitAuthFlowsTypeCustomAuthFlowOnly per API docs.

},
})
}

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

I think we'll need at least one more test to exercise as many fields as we can. I'd usually call such test TestAccAWSCognitoUserPoolClient_allFields.

},

"allowed_oauth_scopes": {
Type: schema.TypeList,

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

AFAIK (correct me if I'm wrong) ordering is not significant in this case, so we should make this field TypeSet.

},

"read_attributes": {
Type: schema.TypeList,

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

AFAIK (correct me if I'm wrong) ordering is not significant in this case, so we should make this field TypeSet.

},

"write_attributes": {
Type: schema.TypeList,

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

AFAIK (correct me if I'm wrong) ordering is not significant in this case, so we should make this field TypeSet.

},

"explicit_auth_flows": {
Type: schema.TypeList,

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

AFAIK (correct me if I'm wrong) ordering is not significant in this case, so we should make this field TypeSet.

},

"allowed_oauth_flows": {
Type: schema.TypeList,

This comment has been minimized.

@radeksimko

radeksimko Dec 11, 2017
Member

AFAIK (correct me if I'm wrong) ordering is not significant in this case, so we should make this field TypeSet.

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Dec 11, 2017

@radeksimko changes made. I'll make up some tests tonight :)

CheckDestroy: testAccCheckAWSCognitoUserPoolClientDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCognitoUserPoolClientConfig_basic(name),

This comment has been minimized.

@radeksimko

radeksimko Dec 12, 2017
Member

I think you're referencing wrong config here 😉

Let me know when it's ready for another round of review.

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Dec 12, 2017

@radeksimko I've changed the test, I was going to run the acceptance test but wanted to run just the user pool client ones if possible. I can't remember how to do this.... ?

Edit: Got it !

@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Dec 12, 2017

@radeksimko Tests corrected and working:

make testacc TESTARGS="-run=TestAccAWSCognitoUserPoolClient_*"
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test $(go list ./... |grep -v 'vendor') -v -run=TestAccAWSCognitoUserPoolClient_* -timeout 120m
?   	github.com/terraform-providers/terraform-provider-aws	[no test files]
=== RUN   TestAccAWSCognitoUserPoolClient_basic
--- PASS: TestAccAWSCognitoUserPoolClient_basic (21.63s)
=== RUN   TestAccAWSCognitoUserPoolClient_allFields
--- PASS: TestAccAWSCognitoUserPoolClient_allFields (19.32s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	40.966s
@radeksimko
Copy link
Member

@radeksimko radeksimko commented Jan 3, 2018

Hi @psyvision
it looks like this is almost ready for the final review & merge, there are just some conflicts as it seems there are some unrelated commits in your branch, possibly as a result of earlier conflict resolution?

I'd recommend using interactive rebase and remove all unrelated commits from the branch, see https://git-scm.com/book/id/v2/Git-Tools-Rewriting-History or let me know if you need help with that. Eventually I can try and resolve it for you.

@psyvision psyvision force-pushed the psyvision:master branch Jan 3, 2018
@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Jan 3, 2018

Well that's royally buggered it!

@psyvision psyvision force-pushed the psyvision:master branch 2 times, most recently Jan 3, 2018
@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Jan 4, 2018

@radeksimko was getting late last night and I kept messing up the rebase. I need to just drop commit 52143f4, the ses changes and then I think it's done properly.

@psyvision psyvision force-pushed the psyvision:master branch Jan 4, 2018
@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Jan 4, 2018

@radeksimko done!

@et304383
Copy link

@et304383 et304383 commented Jan 4, 2018

Anything else holding this up folks? We are immediately dealing with an issue with creating the following:

  • cognito user pool
  • cognito user pool client
  • cognito identity using the user pool client

Without the user pool client support we're going to have to hack something together with:

  • terraform dir 1
  • python script
  • terraform dir 2 with numerous data source lookups
@serialseb
Copy link

@serialseb serialseb commented Jan 4, 2018

if that helps, in the meantime, i use this:

resource "aws_cloudformation_stack" "user_pool_client" {
  name          = "${var.name}-user-pool-client"
  template_body = "${file("${path.module}/templates/stack.yml")}"
  on_failure    = "DELETE"

  parameters {
    UserPoolId = "${var.user_pool_id}"
    ClientName = "${var.name}"
  }
}

with a cloudformation yml

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  UserPoolId:
    Type: String
  ClientName:
    Type: String
Resources:
  UserPoolClient:
    Type: 'AWS::Cognito::UserPoolClient'
    Properties:
      UserPoolId: !Ref UserPoolId
      ClientName: !Ref ClientName
      GenerateSecret: False
      RefreshTokenValidity: xxx
      ExplicitAuthFlows:
        - xxx
Outputs:
  Id:
    Value:
      Ref: UserPoolClient

and for on top of that, for the stuff not in cloudformation



resource "null_resource" "user_pool_client_identities" {
  depends_on = ["aws_cloudformation_stack.user_pool_client"]
  triggers {
    client_id = "${aws_cloudformation_stack.user_pool_client.outputs["Id"]}"
    stack        = "${aws_cloudformation_stack.user_pool_client.template_body}"
    user_pool_id = "${var.user_pool_id}"
    oauth_flows = "${join("", var.allowed_oauth_flows)}"
    oauth_scopes = "${join("", var.allowed_oauth_scopes)}"
  }

  provisioner "local-exec" {
    when ="create"
    command = <<SCRIPT
aws cognito-idp update-user-pool-client \
      --profile wf \
      --user-pool-id ${var.user_pool_id} \
      --client-id ${aws_cloudformation_stack.user_pool_client.outputs["Id"]} \
      --supported-identity-providers ${join(" ", formatlist("\"%s\"", var.supported_identity_providers))} \
      --callback-urls '[${join(",", formatlist("\"%s\"", var.callback_urls))}]' \
      --logout-urls '[${join(",", formatlist("\"%s\"", var.logout_urls))}]' \
      --allowed-o-auth-flows ${join(" ", formatlist("\"%s\"", var.allowed_oauth_flows))} \
      --allowed-o-auth-scopes ${join(" ", formatlist("\"%s\"", var.allowed_oauth_scopes))}
SCRIPT
  }
}

I've built that as a module, until the resource is ready.

@et304383
Copy link

@et304383 et304383 commented Jan 4, 2018

@serialseb this is amazing. Thanks so much. I didn't know you could write custom resources backed by shell commands. You rock.

Copy link
Member

@radeksimko radeksimko left a comment

LGTM now, thanks for the patience and all changes.

aws/provider.go Outdated
@@ -293,7 +293,7 @@ func Provider() terraform.ResourceProvider {
"aws_cognito_identity_pool_roles_attachment": resourceAwsCognitoIdentityPoolRolesAttachment(),
"aws_cognito_user_pool": resourceAwsCognitoUserPool(),
"aws_cognito_user_pool_domain": resourceAwsCognitoUserPoolDomain(),
"aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(),
"aws_cognito_user_pool_client": resourceAwsCognitoUserPoolClient(),

This comment has been minimized.

@radeksimko

radeksimko Jan 11, 2018
Member

I believe that the removal of aws_autoscaling_lifecycle_hook was not intended here - I'll address that in a separate commit.

aws/resource_aws_cognito_user_pool_client.go Outdated
},
},

// analytics_configuration

This comment has been minimized.

@radeksimko

radeksimko Jan 11, 2018
Member

I'll add TODO here as a reminder and to make it clearer what the comment means.

@radeksimko radeksimko force-pushed the psyvision:master branch 2 times, most recently Jan 11, 2018
@radeksimko radeksimko closed this Jan 11, 2018
@radeksimko radeksimko force-pushed the psyvision:master branch to 1958fc8 Jan 11, 2018
@psyvision
Copy link
Contributor Author

@psyvision psyvision commented Jan 11, 2018

Thank you @radeksimko!

@radeksimko
Copy link
Member

@radeksimko radeksimko commented Jan 11, 2018

I didn't mean to close that... wanted to cleanup your git history and somehow managed to close it.
Anyways it's now in master under c583147b8c8b872c6c06dddee62ceb0a7b410646.

Just a friendly note for future PRs:
It can make everyone's life much easier if you open PR from a branch, not from master. It's easier for rebasing, resolving conflicts etc. 😉

@et304383
Copy link

@et304383 et304383 commented Jan 11, 2018

I'm a little confused now. @radeksimko is user pool client now in master? Are we just waiting for a new terraform version?

@radeksimko
Copy link
Member

@radeksimko radeksimko commented Jan 11, 2018

it's in master, will be part of the next release.

@bflad
Copy link
Member

@bflad bflad commented Jan 12, 2018

This has been released in terraform-provider-aws version 1.7.0. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.

@hashibot
Copy link

@hashibot hashibot bot commented Apr 8, 2020

I'm going to lock this issue because it has been closed for 30 days . This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@hashibot hashibot bot locked and limited conversation to collaborators Apr 8, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

7 participants
You can’t perform that action at this time.