From ba239a12597c9a5c46ab3da0e0fa34731bf04d3c Mon Sep 17 00:00:00 2001 From: Andrew Bulford Date: Fri, 8 Oct 2021 13:06:09 +0100 Subject: [PATCH 1/6] Use existing function for nil string setting In the previous PR (#138) I added a `NilString` function and used it to return `nil` if a string was empty, or a pointer to the string otherwise, but this functionality is already available via the `readStringPtrFromResource` function, so use that instead. --- kong/resource_kong_consumer.go | 4 ++-- kong/utils.go | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/kong/resource_kong_consumer.go b/kong/resource_kong_consumer.go index 2193a63..9e4515a 100644 --- a/kong/resource_kong_consumer.go +++ b/kong/resource_kong_consumer.go @@ -43,8 +43,8 @@ func resourceKongConsumer() *schema.Resource { func resourceKongConsumerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { consumerRequest := &kong.Consumer{ - Username: NilString(d.Get("username").(string)), - CustomID: NilString(d.Get("custom_id").(string)), + Username: readStringPtrFromResource(d, "username"), + CustomID: readStringPtrFromResource(d, "custom_id"), Tags: readStringArrayPtrFromResource(d, "tags"), } diff --git a/kong/utils.go b/kong/utils.go index f524adc..c9c24ca 100644 --- a/kong/utils.go +++ b/kong/utils.go @@ -154,13 +154,3 @@ func IDToString(v *string) string { } return *v } - -// NilString converts a string to a string pointer, -// or if empty returns nil. -func NilString(str string) *string { - if str == "" { - return nil - } else { - return kong.String(str) - } -} From 0393312e8884c15a9eac4723a9f63a8b22214f2e Mon Sep 17 00:00:00 2001 From: Andrew Bulford Date: Fri, 8 Oct 2021 13:12:00 +0100 Subject: [PATCH 2/6] Add `kong_consumer_key_auth` resource files This new resource is similar to `kong_consumer_basic_auth` so is being based on that. Create direct copies of the resource file and its tests for now so diffs to these files can be seen more clearly in the next commit. --- kong/resource_kong_consumer_key_auth.go | 137 +++++++++++++++++++ kong/resource_kong_consumer_key_auth_test.go | 130 ++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 kong/resource_kong_consumer_key_auth.go create mode 100644 kong/resource_kong_consumer_key_auth_test.go diff --git a/kong/resource_kong_consumer_key_auth.go b/kong/resource_kong_consumer_key_auth.go new file mode 100644 index 0000000..a71be41 --- /dev/null +++ b/kong/resource_kong_consumer_key_auth.go @@ -0,0 +1,137 @@ +package kong + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/kong/go-kong/kong" +) + +func resourceKongConsumerBasicAuth() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceKongConsumerBasicAuthCreate, + ReadContext: resourceKongConsumerBasicAuthRead, + DeleteContext: resourceKongConsumerBasicAuthDelete, + UpdateContext: resourceKongConsumerBasicAuthUpdate, + Schema: map[string]*schema.Schema{ + "consumer_id": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "username": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "password": { + Type: schema.TypeString, + Required: true, + ForceNew: false, + }, + "tags": { + Type: schema.TypeList, + Optional: true, + ForceNew: false, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func resourceKongConsumerBasicAuthCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + BasicAuthRequest := &kong.BasicAuth{ + Username: kong.String(d.Get("username").(string)), + Password: kong.String(d.Get("password").(string)), + Tags: readStringArrayPtrFromResource(d, "tags"), + } + + consumerId := kong.String(d.Get("consumer_id").(string)) + + client := meta.(*config).adminClient.BasicAuths + basicAuth, err := client.Create(ctx, consumerId, BasicAuthRequest) + + if err != nil { + return diag.FromErr(fmt.Errorf("failed to create kong basic auth: %v error: %v", BasicAuthRequest, err)) + } + + d.SetId(buildConsumerPairID(*basicAuth.ID, *consumerId)) + + return resourceKongConsumerBasicAuthRead(ctx, d, meta) +} + +func resourceKongConsumerBasicAuthUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + id, err := splitConsumerID(d.Id()) + + BasicAuthRequest := &kong.BasicAuth{ + ID: kong.String(id.ID), + Username: kong.String(d.Get("username").(string)), + Password: kong.String(d.Get("password").(string)), + Tags: readStringArrayPtrFromResource(d, "tags"), + } + + consumerId := kong.String(d.Get("consumer_id").(string)) + + client := meta.(*config).adminClient.BasicAuths + _, err = client.Update(ctx, consumerId, BasicAuthRequest) + + if err != nil { + return diag.FromErr(fmt.Errorf("error updating kong basic auth: %s", err)) + } + + return resourceKongConsumerBasicAuthRead(ctx, d, meta) +} + +func resourceKongConsumerBasicAuthRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + id, err := splitConsumerID(d.Id()) + if err != nil { + return diag.FromErr(err) + } + + client := meta.(*config).adminClient.BasicAuths + basicAuth, err := client.Get(ctx, kong.String(id.ConsumerID), kong.String(id.ID)) + + if kong.IsNotFoundErr(err) { + d.SetId("") + } else if err != nil { + return diag.FromErr(fmt.Errorf("could not find kong ACLGroup with id: %s error: %v", id, err)) + } + + if basicAuth == nil { + d.SetId("") + } else { + err = d.Set("consumer_id", basicAuth.Consumer.ID) + if err != nil { + return diag.FromErr(err) + } + err = d.Set("username", basicAuth.Username) + if err != nil { + return diag.FromErr(err) + } + err = d.Set("tags", basicAuth.Tags) + if err != nil { + return diag.FromErr(err) + } + } + + return diags +} + +func resourceKongConsumerBasicAuthDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + var diags diag.Diagnostics + id, err := splitConsumerID(d.Id()) + if err != nil { + return diag.FromErr(err) + } + client := meta.(*config).adminClient.BasicAuths + err = client.Delete(ctx, kong.String(id.ConsumerID), kong.String(id.ID)) + + if err != nil { + return diag.FromErr(fmt.Errorf("could not delete kong basic auth: %v", err)) + } + + return diags +} diff --git a/kong/resource_kong_consumer_key_auth_test.go b/kong/resource_kong_consumer_key_auth_test.go new file mode 100644 index 0000000..16a9fe9 --- /dev/null +++ b/kong/resource_kong_consumer_key_auth_test.go @@ -0,0 +1,130 @@ +package kong + +import ( + "context" + "fmt" + "testing" + + "github.com/kong/go-kong/kong" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccConsumerBasicAuth(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckConsumerBasicAuthDestroy, + Steps: []resource.TestStep{ + { + Config: testCreateConsumerBasicAuthConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckConsumerBasicAuthExists("kong_consumer_basic_auth.consumer_basic_auth"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "username", "foo"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.#", "1"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.0", "myTag"), + ), + }, + { + Config: testUpdateConsumerBasicAuthConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckConsumerBasicAuthExists("kong_consumer_basic_auth.consumer_basic_auth"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "username", "foo_updated"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.#", "2"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.0", "myTag"), + resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.1", "anotherTag"), + ), + }, + }, + }) +} + +func testAccCheckConsumerBasicAuthDestroy(state *terraform.State) error { + + client := testAccProvider.Meta().(*config).adminClient.BasicAuths + + resources := getResourcesByType("kong_consumer_basic_auth", state) + + if len(resources) != 1 { + return fmt.Errorf("expecting only 1 consumer basic auth resource found %v", len(resources)) + } + + id, err := splitConsumerID(resources[0].Primary.ID) + ConsumerBasicAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID)) + + if !kong.IsNotFoundErr(err) && err != nil { + return fmt.Errorf("error calling get consumer auth by id: %v", err) + } + + if ConsumerBasicAuth != nil { + return fmt.Errorf("jwt auth %s still exists, %+v", id.ID, ConsumerBasicAuth) + } + + return nil +} + +func testAccCheckConsumerBasicAuthExists(resourceKey string) resource.TestCheckFunc { + + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceKey] + + if !ok { + return fmt.Errorf("not found: %s", resourceKey) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("no ID is set") + } + + client := testAccProvider.Meta().(*config).adminClient.BasicAuths + id, err := splitConsumerID(rs.Primary.ID) + + ConsumerBasicAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID)) + + if err != nil { + return err + } + + if ConsumerBasicAuth == nil { + return fmt.Errorf("ConsumerBasicAuth with id %v not found", id.ID) + } + + return nil + } +} + +const testCreateConsumerBasicAuthConfig = ` +resource "kong_consumer" "my_consumer" { + username = "User1" + custom_id = "123" +} + +resource "kong_plugin" "basic_auth_plugin" { + name = "basic-auth" +} + +resource "kong_consumer_basic_auth" "consumer_basic_auth" { + consumer_id = "${kong_consumer.my_consumer.id}" + username = "foo" + password = "bar" + tags = ["myTag"] +} +` +const testUpdateConsumerBasicAuthConfig = ` +resource "kong_consumer" "my_consumer" { + username = "User1" + custom_id = "123" +} + +resource "kong_plugin" "basic_auth_plugin" { + name = "basic-auth" +} + +resource "kong_consumer_basic_auth" "consumer_basic_auth" { + consumer_id = "${kong_consumer.my_consumer.id}" + username = "foo_updated" + password = "bar_updated" + tags = ["myTag", "anotherTag"] +} +` From c689e4d0d8b2bde5c20e4e2f2849d38ea078dc4d Mon Sep 17 00:00:00 2001 From: Andrew Bulford Date: Fri, 8 Oct 2021 13:43:13 +0100 Subject: [PATCH 3/6] Implement `kong_consumer_key_auth` resource By adapting the previously copied `kong_consumer_basic_auth` resource. Note that the TTL property is deliberately omitted from the resource, because the value is not stable - when retrieved from Kong the value returned is the remaining TTL based on when it was created, so it's not very well suited to Terraforming. Possibly it could be a computed value, but will be left out for now. --- kong/provider.go | 1 + kong/resource_kong_consumer_key_auth.go | 84 +++++++++----------- kong/resource_kong_consumer_key_auth_test.go | 83 ++++++++++--------- 3 files changed, 80 insertions(+), 88 deletions(-) diff --git a/kong/provider.go b/kong/provider.go index 6b06d9c..d3dde40 100644 --- a/kong/provider.go +++ b/kong/provider.go @@ -71,6 +71,7 @@ func Provider() *schema.Provider { "kong_consumer": resourceKongConsumer(), "kong_consumer_acl": resourceKongConsumerACL(), "kong_consumer_basic_auth": resourceKongConsumerBasicAuth(), + "kong_consumer_key_auth": resourceKongConsumerKeyAuth(), "kong_plugin": resourceKongPlugin(), "kong_upstream": resourceKongUpstream(), "kong_target": resourceKongTarget(), diff --git a/kong/resource_kong_consumer_key_auth.go b/kong/resource_kong_consumer_key_auth.go index a71be41..a0925ef 100644 --- a/kong/resource_kong_consumer_key_auth.go +++ b/kong/resource_kong_consumer_key_auth.go @@ -9,27 +9,23 @@ import ( "github.com/kong/go-kong/kong" ) -func resourceKongConsumerBasicAuth() *schema.Resource { +func resourceKongConsumerKeyAuth() *schema.Resource { return &schema.Resource{ - CreateContext: resourceKongConsumerBasicAuthCreate, - ReadContext: resourceKongConsumerBasicAuthRead, - DeleteContext: resourceKongConsumerBasicAuthDelete, - UpdateContext: resourceKongConsumerBasicAuthUpdate, + CreateContext: resourceKongConsumerKeyAuthCreate, + ReadContext: resourceKongConsumerKeyAuthRead, + DeleteContext: resourceKongConsumerKeyAuthDelete, + UpdateContext: resourceKongConsumerKeyAuthUpdate, Schema: map[string]*schema.Schema{ "consumer_id": { Type: schema.TypeString, Required: true, ForceNew: false, }, - "username": { - Type: schema.TypeString, - Required: true, - ForceNew: false, - }, - "password": { - Type: schema.TypeString, - Required: true, - ForceNew: false, + "key": { + Type: schema.TypeString, + Optional: true, + ForceNew: false, + Sensitive: true, }, "tags": { Type: schema.TypeList, @@ -41,77 +37,75 @@ func resourceKongConsumerBasicAuth() *schema.Resource { } } -func resourceKongConsumerBasicAuthCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - BasicAuthRequest := &kong.BasicAuth{ - Username: kong.String(d.Get("username").(string)), - Password: kong.String(d.Get("password").(string)), - Tags: readStringArrayPtrFromResource(d, "tags"), +func resourceKongConsumerKeyAuthCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + KeyAuthRequest := &kong.KeyAuth{ + Key: readStringPtrFromResource(d, "key"), + Tags: readStringArrayPtrFromResource(d, "tags"), } consumerId := kong.String(d.Get("consumer_id").(string)) - client := meta.(*config).adminClient.BasicAuths - basicAuth, err := client.Create(ctx, consumerId, BasicAuthRequest) + client := meta.(*config).adminClient.KeyAuths + keyAuth, err := client.Create(ctx, consumerId, KeyAuthRequest) if err != nil { - return diag.FromErr(fmt.Errorf("failed to create kong basic auth: %v error: %v", BasicAuthRequest, err)) + return diag.FromErr(fmt.Errorf("failed to create kong key auth: %v error: %v", KeyAuthRequest, err)) } - d.SetId(buildConsumerPairID(*basicAuth.ID, *consumerId)) + d.SetId(buildConsumerPairID(*keyAuth.ID, *consumerId)) - return resourceKongConsumerBasicAuthRead(ctx, d, meta) + return resourceKongConsumerKeyAuthRead(ctx, d, meta) } -func resourceKongConsumerBasicAuthUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceKongConsumerKeyAuthUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { id, err := splitConsumerID(d.Id()) - BasicAuthRequest := &kong.BasicAuth{ - ID: kong.String(id.ID), - Username: kong.String(d.Get("username").(string)), - Password: kong.String(d.Get("password").(string)), - Tags: readStringArrayPtrFromResource(d, "tags"), + KeyAuthRequest := &kong.KeyAuth{ + ID: kong.String(id.ID), + Key: readStringPtrFromResource(d, "key"), + Tags: readStringArrayPtrFromResource(d, "tags"), } consumerId := kong.String(d.Get("consumer_id").(string)) - client := meta.(*config).adminClient.BasicAuths - _, err = client.Update(ctx, consumerId, BasicAuthRequest) + client := meta.(*config).adminClient.KeyAuths + _, err = client.Update(ctx, consumerId, KeyAuthRequest) if err != nil { - return diag.FromErr(fmt.Errorf("error updating kong basic auth: %s", err)) + return diag.FromErr(fmt.Errorf("error updating kong key auth: %s", err)) } - return resourceKongConsumerBasicAuthRead(ctx, d, meta) + return resourceKongConsumerKeyAuthRead(ctx, d, meta) } -func resourceKongConsumerBasicAuthRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceKongConsumerKeyAuthRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics id, err := splitConsumerID(d.Id()) if err != nil { return diag.FromErr(err) } - client := meta.(*config).adminClient.BasicAuths - basicAuth, err := client.Get(ctx, kong.String(id.ConsumerID), kong.String(id.ID)) + client := meta.(*config).adminClient.KeyAuths + keyAuth, err := client.Get(ctx, kong.String(id.ConsumerID), kong.String(id.ID)) if kong.IsNotFoundErr(err) { d.SetId("") } else if err != nil { - return diag.FromErr(fmt.Errorf("could not find kong ACLGroup with id: %s error: %v", id, err)) + return diag.FromErr(fmt.Errorf("could not find kong key auth with id: %s error: %v", id, err)) } - if basicAuth == nil { + if keyAuth == nil { d.SetId("") } else { - err = d.Set("consumer_id", basicAuth.Consumer.ID) + err = d.Set("consumer_id", keyAuth.Consumer.ID) if err != nil { return diag.FromErr(err) } - err = d.Set("username", basicAuth.Username) + err = d.Set("key", keyAuth.Key) if err != nil { return diag.FromErr(err) } - err = d.Set("tags", basicAuth.Tags) + err = d.Set("tags", keyAuth.Tags) if err != nil { return diag.FromErr(err) } @@ -120,17 +114,17 @@ func resourceKongConsumerBasicAuthRead(ctx context.Context, d *schema.ResourceDa return diags } -func resourceKongConsumerBasicAuthDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { +func resourceKongConsumerKeyAuthDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { var diags diag.Diagnostics id, err := splitConsumerID(d.Id()) if err != nil { return diag.FromErr(err) } - client := meta.(*config).adminClient.BasicAuths + client := meta.(*config).adminClient.KeyAuths err = client.Delete(ctx, kong.String(id.ConsumerID), kong.String(id.ID)) if err != nil { - return diag.FromErr(fmt.Errorf("could not delete kong basic auth: %v", err)) + return diag.FromErr(fmt.Errorf("could not delete kong key auth: %v", err)) } return diags diff --git a/kong/resource_kong_consumer_key_auth_test.go b/kong/resource_kong_consumer_key_auth_test.go index 16a9fe9..df34e69 100644 --- a/kong/resource_kong_consumer_key_auth_test.go +++ b/kong/resource_kong_consumer_key_auth_test.go @@ -5,66 +5,65 @@ import ( "fmt" "testing" - "github.com/kong/go-kong/kong" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/kong/go-kong/kong" ) -func TestAccConsumerBasicAuth(t *testing.T) { +func TestAccConsumerKeyAuth(t *testing.T) { resource.Test(t, resource.TestCase{ Providers: testAccProviders, - CheckDestroy: testAccCheckConsumerBasicAuthDestroy, + CheckDestroy: testAccCheckConsumerKeyAuthDestroy, Steps: []resource.TestStep{ { - Config: testCreateConsumerBasicAuthConfig, + Config: testCreateConsumerKeyAuthConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckConsumerBasicAuthExists("kong_consumer_basic_auth.consumer_basic_auth"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "username", "foo"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.#", "1"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.0", "myTag"), + testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "key", "foo"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "1"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"), ), }, { - Config: testUpdateConsumerBasicAuthConfig, + Config: testUpdateConsumerKeyAuthConfig, Check: resource.ComposeTestCheckFunc( - testAccCheckConsumerBasicAuthExists("kong_consumer_basic_auth.consumer_basic_auth"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "username", "foo_updated"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.#", "2"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.0", "myTag"), - resource.TestCheckResourceAttr("kong_consumer_basic_auth.consumer_basic_auth", "tags.1", "anotherTag"), + testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "key", "foo_updated"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "2"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.1", "anotherTag"), ), }, }, }) } -func testAccCheckConsumerBasicAuthDestroy(state *terraform.State) error { +func testAccCheckConsumerKeyAuthDestroy(state *terraform.State) error { - client := testAccProvider.Meta().(*config).adminClient.BasicAuths + client := testAccProvider.Meta().(*config).adminClient.KeyAuths - resources := getResourcesByType("kong_consumer_basic_auth", state) + resources := getResourcesByType("kong_consumer_key_auth", state) if len(resources) != 1 { - return fmt.Errorf("expecting only 1 consumer basic auth resource found %v", len(resources)) + return fmt.Errorf("expecting only 1 consumer key auth resource found %v", len(resources)) } id, err := splitConsumerID(resources[0].Primary.ID) - ConsumerBasicAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID)) + ConsumerKeyAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID)) if !kong.IsNotFoundErr(err) && err != nil { return fmt.Errorf("error calling get consumer auth by id: %v", err) } - if ConsumerBasicAuth != nil { - return fmt.Errorf("jwt auth %s still exists, %+v", id.ID, ConsumerBasicAuth) + if ConsumerKeyAuth != nil { + return fmt.Errorf("key auth %s still exists, %+v", id.ID, ConsumerKeyAuth) } return nil } -func testAccCheckConsumerBasicAuthExists(resourceKey string) resource.TestCheckFunc { +func testAccCheckConsumerKeyAuthExists(resourceKey string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceKey] @@ -77,54 +76,52 @@ func testAccCheckConsumerBasicAuthExists(resourceKey string) resource.TestCheckF return fmt.Errorf("no ID is set") } - client := testAccProvider.Meta().(*config).adminClient.BasicAuths + client := testAccProvider.Meta().(*config).adminClient.KeyAuths id, err := splitConsumerID(rs.Primary.ID) - ConsumerBasicAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID)) + ConsumerKeyAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID)) if err != nil { return err } - if ConsumerBasicAuth == nil { - return fmt.Errorf("ConsumerBasicAuth with id %v not found", id.ID) + if ConsumerKeyAuth == nil { + return fmt.Errorf("ConsumerKeyAuth with id %v not found", id.ID) } return nil } } -const testCreateConsumerBasicAuthConfig = ` +const testCreateConsumerKeyAuthConfig = ` resource "kong_consumer" "my_consumer" { username = "User1" custom_id = "123" } -resource "kong_plugin" "basic_auth_plugin" { - name = "basic-auth" +resource "kong_plugin" "key_auth_plugin" { + name = "key-auth" } -resource "kong_consumer_basic_auth" "consumer_basic_auth" { - consumer_id = "${kong_consumer.my_consumer.id}" - username = "foo" - password = "bar" - tags = ["myTag"] +resource "kong_consumer_key_auth" "consumer_key_auth" { + consumer_id = "${kong_consumer.my_consumer.id}" + key = "foo" + tags = ["myTag"] } ` -const testUpdateConsumerBasicAuthConfig = ` +const testUpdateConsumerKeyAuthConfig = ` resource "kong_consumer" "my_consumer" { username = "User1" custom_id = "123" } -resource "kong_plugin" "basic_auth_plugin" { - name = "basic-auth" +resource "kong_plugin" "key_auth_plugin" { + name = "key-auth" } -resource "kong_consumer_basic_auth" "consumer_basic_auth" { - consumer_id = "${kong_consumer.my_consumer.id}" - username = "foo_updated" - password = "bar_updated" - tags = ["myTag", "anotherTag"] +resource "kong_consumer_key_auth" "consumer_key_auth" { + consumer_id = "${kong_consumer.my_consumer.id}" + key = "foo_updated" + tags = ["myTag", "anotherTag"] } ` From 5121c7d61c002fcacca5c5b2db047e02a425df5c Mon Sep 17 00:00:00 2001 From: Andrew Bulford Date: Fri, 8 Oct 2021 13:46:20 +0100 Subject: [PATCH 4/6] Add support for auto-generated keys The key doesn't need to be provided, in which case the plugin generates one for us. So mark the property as `computed` and add a test which checks that we get a value returned. --- kong/resource_kong_consumer_key_auth.go | 1 + kong/resource_kong_consumer_key_auth_test.go | 44 ++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/kong/resource_kong_consumer_key_auth.go b/kong/resource_kong_consumer_key_auth.go index a0925ef..febbd5d 100644 --- a/kong/resource_kong_consumer_key_auth.go +++ b/kong/resource_kong_consumer_key_auth.go @@ -24,6 +24,7 @@ func resourceKongConsumerKeyAuth() *schema.Resource { "key": { Type: schema.TypeString, Optional: true, + Computed: true, ForceNew: false, Sensitive: true, }, diff --git a/kong/resource_kong_consumer_key_auth_test.go b/kong/resource_kong_consumer_key_auth_test.go index df34e69..09c71e0 100644 --- a/kong/resource_kong_consumer_key_auth_test.go +++ b/kong/resource_kong_consumer_key_auth_test.go @@ -39,6 +39,35 @@ func TestAccConsumerKeyAuth(t *testing.T) { }) } +func TestAccConsumerKeyAuthComputed(t *testing.T) { + + resource.Test(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: testAccCheckConsumerKeyAuthDestroy, + Steps: []resource.TestStep{ + { + Config: testCreateConsumerKeyAuthConfigKeyComputed, + Check: resource.ComposeTestCheckFunc( + testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"), + resource.TestCheckResourceAttrSet("kong_consumer_key_auth.consumer_key_auth", "key"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "1"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"), + ), + }, + { + Config: testUpdateConsumerKeyAuthConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "key", "foo_updated"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "2"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"), + resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.1", "anotherTag"), + ), + }, + }, + }) +} + func testAccCheckConsumerKeyAuthDestroy(state *terraform.State) error { client := testAccProvider.Meta().(*config).adminClient.KeyAuths @@ -125,3 +154,18 @@ resource "kong_consumer_key_auth" "consumer_key_auth" { tags = ["myTag", "anotherTag"] } ` +const testCreateConsumerKeyAuthConfigKeyComputed = ` +resource "kong_consumer" "my_consumer" { + username = "User1" + custom_id = "123" +} + +resource "kong_plugin" "key_auth_plugin" { + name = "key-auth" +} + +resource "kong_consumer_key_auth" "consumer_key_auth" { + consumer_id = "${kong_consumer.my_consumer.id}" + tags = ["myTag"] +} +` From 01bd7c2a840c523925fbb0b89a3aea622b828243 Mon Sep 17 00:00:00 2001 From: Andrew Bulford Date: Fri, 8 Oct 2021 13:48:38 +0100 Subject: [PATCH 5/6] Fix copy and paste errors These were noticed when adapting the `kong_consumer_key_auth` resource. --- kong/resource_kong_consumer_basic_auth.go | 2 +- kong/resource_kong_consumer_basic_auth_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kong/resource_kong_consumer_basic_auth.go b/kong/resource_kong_consumer_basic_auth.go index 78b08cb..d09962a 100644 --- a/kong/resource_kong_consumer_basic_auth.go +++ b/kong/resource_kong_consumer_basic_auth.go @@ -96,7 +96,7 @@ func resourceKongConsumerBasicAuthRead(ctx context.Context, d *schema.ResourceDa if kong.IsNotFoundErr(err) { d.SetId("") } else if err != nil { - return diag.FromErr(fmt.Errorf("could not find kong ACLGroup with id: %s error: %v", id, err)) + return diag.FromErr(fmt.Errorf("could not find kong basic auth with id: %s error: %v", id, err)) } if basicAuth == nil { diff --git a/kong/resource_kong_consumer_basic_auth_test.go b/kong/resource_kong_consumer_basic_auth_test.go index b0ae5b8..ce3ab59 100644 --- a/kong/resource_kong_consumer_basic_auth_test.go +++ b/kong/resource_kong_consumer_basic_auth_test.go @@ -57,7 +57,7 @@ func testAccCheckConsumerBasicAuthDestroy(state *terraform.State) error { } if ConsumerBasicAuth != nil { - return fmt.Errorf("jwt auth %s still exists, %+v", id.ID, ConsumerBasicAuth) + return fmt.Errorf("basic auth %s still exists, %+v", id.ID, ConsumerBasicAuth) } return nil From 2b14ef2455299d7de8611510506cf030e966a289 Mon Sep 17 00:00:00 2001 From: Andrew Bulford Date: Fri, 8 Oct 2021 14:05:47 +0100 Subject: [PATCH 6/6] Add documentation for `kong_consumer_key_auth` --- docs/resources/consumer_key_auth.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/resources/consumer_key_auth.md diff --git a/docs/resources/consumer_key_auth.md b/docs/resources/consumer_key_auth.md new file mode 100644 index 0000000..ff815d0 --- /dev/null +++ b/docs/resources/consumer_key_auth.md @@ -0,0 +1,28 @@ +# kong_consumer_key_auth + +Resource that allows you to configure the [Key Authentication](https://docs.konghq.com/hub/kong-inc/key-auth/) plugin for a consumer. + +## Example Usage + +```hcl +resource "kong_consumer" "my_consumer" { + username = "User1" + custom_id = "123" +} + +resource "kong_plugin" "key_auth_plugin" { + name = "key-auth" +} + +resource "kong_consumer_key_auth" "consumer_key_auth" { + consumer_id = kong_consumer.my_consumer.id + key = "secret" + tags = ["myTag", "anotherTag"] +} +``` + +## Argument Reference + +* `consumer_id` - (Required) the id of the consumer to associate the credentials to +* `key` - (Optional) Unique key to authenticate the client; if omitted the plugin will generate one +* `tags` - (Optional) A list of strings associated with the consumer key auth for grouping and filtering