-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
Feature/aws cognito resource server #4530
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider" | ||
"github.com/hashicorp/errwrap" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsCognitoResourceServer() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsCognitoResourceServerCreate, | ||
Read: resourceAwsCognitoResourceServerRead, | ||
Update: resourceAwsCognitoResourceServerUpdate, | ||
Delete: resourceAwsCognitoResourceServerDelete, | ||
|
||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
// https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_CreateResourceServer.html | ||
Schema: map[string]*schema.Schema{ | ||
"identifier": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It appears that |
||
}, | ||
"scope": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
MaxItems: 25, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"scope_description": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validateCognitoResourceServerScopeDescription, | ||
}, | ||
"scope_name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validateCognitoResourceServerScopeName, | ||
}, | ||
"scope_identifier": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This attribute is a little awkward as its not defined by the API and is seemingly only used to build the computed |
||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"user_pool_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"scope_identifiers": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsCognitoResourceServerCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).cognitoidpconn | ||
|
||
params := &cognitoidentityprovider.CreateResourceServerInput{ | ||
Identifier: aws.String(d.Get("identifier").(string)), | ||
Name: aws.String(d.Get("name").(string)), | ||
UserPoolId: aws.String(d.Get("user_pool_id").(string)), | ||
} | ||
|
||
if v, ok := d.GetOk("scope"); ok { | ||
configs := v.(*schema.Set).List() | ||
params.Scopes = expandCognitoResourceServerScope(configs) | ||
} | ||
|
||
log.Printf("[DEBUG] Creating Cognito Resource Server: %s", params) | ||
|
||
resp, err := conn.CreateResourceServer(params) | ||
|
||
if err != nil { | ||
return errwrap.Wrapf("Error creating Cognito Resource Server: {{err}}", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor nitpick: We do not need to use |
||
} | ||
|
||
d.SetId(*resp.ResourceServer.Identifier) | ||
|
||
return resourceAwsCognitoResourceServerRead(d, meta) | ||
} | ||
|
||
func resourceAwsCognitoResourceServerRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).cognitoidpconn | ||
|
||
params := &cognitoidentityprovider.DescribeResourceServerInput{ | ||
Identifier: aws.String(d.Id()), | ||
UserPoolId: aws.String(d.Get("user_pool_id").(string)), | ||
} | ||
|
||
log.Printf("[DEBUG] Reading Cognito Resource Server: %s", params) | ||
|
||
resp, err := conn.DescribeResourceServer(params) | ||
|
||
if err != nil { | ||
if isAWSErr(err, "ResourceNotFoundException", "") { | ||
log.Printf("[WARN] Cognito Resource Server %s is already gone", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
return err | ||
} | ||
|
||
d.SetId(*resp.ResourceServer.Identifier) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should not call |
||
d.Set("name", *resp.ResourceServer.Name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To prevent panics, we should ensure that Also |
||
d.Set("user_pool_id", *resp.ResourceServer.UserPoolId) | ||
|
||
scopes := flattenCognitoResourceServerScope(*resp.ResourceServer.Identifier, resp.ResourceServer.Scopes) | ||
if err := d.Set("scope", scopes); err != nil { | ||
return fmt.Errorf("Failed setting schema: %s", err) | ||
} | ||
|
||
var scopeIdentifiers []string | ||
for _, elem := range scopes { | ||
|
||
scopeIdentifier := elem["scope_identifier"].(string) | ||
scopeIdentifiers = append(scopeIdentifiers, scopeIdentifier) | ||
} | ||
d.Set("scope_identifiers", scopeIdentifiers) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this attribute is a non-scalar type, we should perform |
||
return nil | ||
} | ||
|
||
func resourceAwsCognitoResourceServerUpdate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).cognitoidpconn | ||
|
||
params := &cognitoidentityprovider.UpdateResourceServerInput{ | ||
Identifier: aws.String(d.Id()), | ||
Name: aws.String(d.Get("name").(string)), | ||
UserPoolId: aws.String(d.Get("user_pool_id").(string)), | ||
} | ||
|
||
log.Printf("[DEBUG] Updating Cognito Resource Server: %s", params) | ||
|
||
_, err := conn.UpdateResourceServer(params) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scopes can be updated but its not being added to the update parameters, so currently they would generate a perpetual difference. |
||
if err != nil { | ||
return errwrap.Wrapf("Error updating Cognito Resource Server: {{err}}", err) | ||
} | ||
|
||
return resourceAwsCognitoResourceServerRead(d, meta) | ||
} | ||
|
||
func resourceAwsCognitoResourceServerDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).cognitoidpconn | ||
|
||
params := &cognitoidentityprovider.DeleteResourceServerInput{ | ||
Identifier: aws.String(d.Id()), | ||
UserPoolId: aws.String(d.Get("user_pool_id").(string)), | ||
} | ||
|
||
log.Printf("[DEBUG] Deleting Resource Server: %s", params) | ||
|
||
_, err := conn.DeleteResourceServer(params) | ||
|
||
if err != nil { | ||
return errwrap.Wrapf("Error deleting Resource Server: {{err}}", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should check for |
||
} | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
package aws | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSCognitoResourceServer_basic(t *testing.T) { | ||
identifier := fmt.Sprintf("tf-acc-test-resource-server-id-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) | ||
name := fmt.Sprintf("tf-acc-test-resource-server-name-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) | ||
poolName := fmt.Sprintf("tf-acc-test-pool-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSCognitoResourceServerDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAWSCognitoResourceServerConfig_basic(identifier, name, poolName), | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
testAccCheckAWSCognitoResourceServerExists("aws_cognito_resource_server.main"), | ||
resource.TestCheckResourceAttr("aws_cognito_resource_server.main", "identifier", identifier), | ||
resource.TestCheckResourceAttr("aws_cognito_resource_server.main", "name", name), | ||
resource.TestCheckResourceAttr("aws_cognito_user_pool.main", "name", poolName), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccAWSCognitoResourceServer_full(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should descriptively name this |
||
identifier := fmt.Sprintf("tf-acc-test-resource-server-id-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) | ||
name := fmt.Sprintf("tf-acc-test-resource-server-name-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) | ||
poolName := fmt.Sprintf("tf-acc-test-pool-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSCognitoResourceServerDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAWSCognitoResourceServerConfig_full(identifier, name, poolName), | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
testAccCheckAWSCognitoResourceServerExists("aws_cognito_resource_server.main"), | ||
resource.TestCheckResourceAttr("aws_cognito_resource_server.main", "identifier", identifier), | ||
resource.TestCheckResourceAttr("aws_cognito_resource_server.main", "name", name), | ||
resource.TestCheckResourceAttrSet("aws_cognito_resource_server.main", "scope_identifiers"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is currently failing:
Did you mean to do this? resource.TestCheckResourceAttr("aws_cognito_resource_server.main", "scope.#", "2"), |
||
resource.TestCheckResourceAttr("aws_cognito_user_pool.main", "name", poolName), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSCognitoResourceServerExists(n string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return errors.New("No Cognito Resource Server ID is set") | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).cognitoidpconn | ||
|
||
_, err := conn.DescribeResourceServer(&cognitoidentityprovider.DescribeResourceServerInput{ | ||
Identifier: aws.String(rs.Primary.ID), | ||
UserPoolId: aws.String(rs.Primary.Attributes["user_pool_id"]), | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckAWSCognitoResourceServerDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).cognitoidpconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_cognito_resource_server" { | ||
continue | ||
} | ||
|
||
_, err := conn.DescribeResourceServer(&cognitoidentityprovider.DescribeResourceServerInput{ | ||
Identifier: aws.String(rs.Primary.ID), | ||
UserPoolId: aws.String(rs.Primary.Attributes["user_pool_id"]), | ||
}) | ||
|
||
if err != nil { | ||
if isAWSErr(err, "ResourceNotFoundException", "") { | ||
return nil | ||
} | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccAWSCognitoResourceServerConfig_basic(identifier string, name string, poolName string) string { | ||
return fmt.Sprintf(` | ||
resource "aws_cognito_resource_server" "main" { | ||
identifier = "%s" | ||
name = "%s" | ||
user_pool_id = "${aws_cognito_user_pool.main.id}" | ||
} | ||
|
||
resource "aws_cognito_user_pool" "main" { | ||
name = "%s" | ||
} | ||
`, identifier, name, poolName) | ||
} | ||
|
||
func testAccAWSCognitoResourceServerConfig_full(identifier string, name string, poolName string) string { | ||
return fmt.Sprintf(` | ||
resource "aws_cognito_resource_server" "main" { | ||
identifier = "%s" | ||
name = "%s" | ||
|
||
scope = { | ||
scope_name = "scope_1_name" | ||
scope_description = "scope_1_description" | ||
} | ||
|
||
scope = { | ||
scope_name = "scope_2_name" | ||
scope_description = "scope_2_description" | ||
} | ||
|
||
user_pool_id = "${aws_cognito_user_pool.main.id}" | ||
} | ||
|
||
resource "aws_cognito_user_pool" "main" { | ||
name = "%s" | ||
} | ||
`, identifier, name, poolName) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current resource ID (only Identifier) does not have enough information to work with the passthrough importer. We also need the user pool ID so the read function can work directly from the ID.
In this case, we should probably prepend the user pool ID to the resource ID, e.g.