Skip to content

Commit 82d072e

Browse files
Merge pull request #139 from andrew-bulford-form3/add-kong-consumer-key-auth-resource
Add `kong_consumer_key_auth` resource
2 parents f3e7282 + 2b14ef2 commit 82d072e

8 files changed

+336
-14
lines changed

docs/resources/consumer_key_auth.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# kong_consumer_key_auth
2+
3+
Resource that allows you to configure the [Key Authentication](https://docs.konghq.com/hub/kong-inc/key-auth/) plugin for a consumer.
4+
5+
## Example Usage
6+
7+
```hcl
8+
resource "kong_consumer" "my_consumer" {
9+
username = "User1"
10+
custom_id = "123"
11+
}
12+
13+
resource "kong_plugin" "key_auth_plugin" {
14+
name = "key-auth"
15+
}
16+
17+
resource "kong_consumer_key_auth" "consumer_key_auth" {
18+
consumer_id = kong_consumer.my_consumer.id
19+
key = "secret"
20+
tags = ["myTag", "anotherTag"]
21+
}
22+
```
23+
24+
## Argument Reference
25+
26+
* `consumer_id` - (Required) the id of the consumer to associate the credentials to
27+
* `key` - (Optional) Unique key to authenticate the client; if omitted the plugin will generate one
28+
* `tags` - (Optional) A list of strings associated with the consumer key auth for grouping and filtering

kong/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func Provider() *schema.Provider {
7171
"kong_consumer": resourceKongConsumer(),
7272
"kong_consumer_acl": resourceKongConsumerACL(),
7373
"kong_consumer_basic_auth": resourceKongConsumerBasicAuth(),
74+
"kong_consumer_key_auth": resourceKongConsumerKeyAuth(),
7475
"kong_plugin": resourceKongPlugin(),
7576
"kong_upstream": resourceKongUpstream(),
7677
"kong_target": resourceKongTarget(),

kong/resource_kong_consumer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func resourceKongConsumer() *schema.Resource {
4343
func resourceKongConsumerCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
4444

4545
consumerRequest := &kong.Consumer{
46-
Username: NilString(d.Get("username").(string)),
47-
CustomID: NilString(d.Get("custom_id").(string)),
46+
Username: readStringPtrFromResource(d, "username"),
47+
CustomID: readStringPtrFromResource(d, "custom_id"),
4848
Tags: readStringArrayPtrFromResource(d, "tags"),
4949
}
5050

kong/resource_kong_consumer_basic_auth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ func resourceKongConsumerBasicAuthRead(ctx context.Context, d *schema.ResourceDa
9696
if kong.IsNotFoundErr(err) {
9797
d.SetId("")
9898
} else if err != nil {
99-
return diag.FromErr(fmt.Errorf("could not find kong ACLGroup with id: %s error: %v", id, err))
99+
return diag.FromErr(fmt.Errorf("could not find kong basic auth with id: %s error: %v", id, err))
100100
}
101101

102102
if basicAuth == nil {

kong/resource_kong_consumer_basic_auth_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func testAccCheckConsumerBasicAuthDestroy(state *terraform.State) error {
5757
}
5858

5959
if ConsumerBasicAuth != nil {
60-
return fmt.Errorf("jwt auth %s still exists, %+v", id.ID, ConsumerBasicAuth)
60+
return fmt.Errorf("basic auth %s still exists, %+v", id.ID, ConsumerBasicAuth)
6161
}
6262

6363
return nil
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package kong
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/kong/go-kong/kong"
10+
)
11+
12+
func resourceKongConsumerKeyAuth() *schema.Resource {
13+
return &schema.Resource{
14+
CreateContext: resourceKongConsumerKeyAuthCreate,
15+
ReadContext: resourceKongConsumerKeyAuthRead,
16+
DeleteContext: resourceKongConsumerKeyAuthDelete,
17+
UpdateContext: resourceKongConsumerKeyAuthUpdate,
18+
Schema: map[string]*schema.Schema{
19+
"consumer_id": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
ForceNew: false,
23+
},
24+
"key": {
25+
Type: schema.TypeString,
26+
Optional: true,
27+
Computed: true,
28+
ForceNew: false,
29+
Sensitive: true,
30+
},
31+
"tags": {
32+
Type: schema.TypeList,
33+
Optional: true,
34+
ForceNew: false,
35+
Elem: &schema.Schema{Type: schema.TypeString},
36+
},
37+
},
38+
}
39+
}
40+
41+
func resourceKongConsumerKeyAuthCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
42+
KeyAuthRequest := &kong.KeyAuth{
43+
Key: readStringPtrFromResource(d, "key"),
44+
Tags: readStringArrayPtrFromResource(d, "tags"),
45+
}
46+
47+
consumerId := kong.String(d.Get("consumer_id").(string))
48+
49+
client := meta.(*config).adminClient.KeyAuths
50+
keyAuth, err := client.Create(ctx, consumerId, KeyAuthRequest)
51+
52+
if err != nil {
53+
return diag.FromErr(fmt.Errorf("failed to create kong key auth: %v error: %v", KeyAuthRequest, err))
54+
}
55+
56+
d.SetId(buildConsumerPairID(*keyAuth.ID, *consumerId))
57+
58+
return resourceKongConsumerKeyAuthRead(ctx, d, meta)
59+
}
60+
61+
func resourceKongConsumerKeyAuthUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
62+
id, err := splitConsumerID(d.Id())
63+
64+
KeyAuthRequest := &kong.KeyAuth{
65+
ID: kong.String(id.ID),
66+
Key: readStringPtrFromResource(d, "key"),
67+
Tags: readStringArrayPtrFromResource(d, "tags"),
68+
}
69+
70+
consumerId := kong.String(d.Get("consumer_id").(string))
71+
72+
client := meta.(*config).adminClient.KeyAuths
73+
_, err = client.Update(ctx, consumerId, KeyAuthRequest)
74+
75+
if err != nil {
76+
return diag.FromErr(fmt.Errorf("error updating kong key auth: %s", err))
77+
}
78+
79+
return resourceKongConsumerKeyAuthRead(ctx, d, meta)
80+
}
81+
82+
func resourceKongConsumerKeyAuthRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
83+
var diags diag.Diagnostics
84+
id, err := splitConsumerID(d.Id())
85+
if err != nil {
86+
return diag.FromErr(err)
87+
}
88+
89+
client := meta.(*config).adminClient.KeyAuths
90+
keyAuth, err := client.Get(ctx, kong.String(id.ConsumerID), kong.String(id.ID))
91+
92+
if kong.IsNotFoundErr(err) {
93+
d.SetId("")
94+
} else if err != nil {
95+
return diag.FromErr(fmt.Errorf("could not find kong key auth with id: %s error: %v", id, err))
96+
}
97+
98+
if keyAuth == nil {
99+
d.SetId("")
100+
} else {
101+
err = d.Set("consumer_id", keyAuth.Consumer.ID)
102+
if err != nil {
103+
return diag.FromErr(err)
104+
}
105+
err = d.Set("key", keyAuth.Key)
106+
if err != nil {
107+
return diag.FromErr(err)
108+
}
109+
err = d.Set("tags", keyAuth.Tags)
110+
if err != nil {
111+
return diag.FromErr(err)
112+
}
113+
}
114+
115+
return diags
116+
}
117+
118+
func resourceKongConsumerKeyAuthDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
119+
var diags diag.Diagnostics
120+
id, err := splitConsumerID(d.Id())
121+
if err != nil {
122+
return diag.FromErr(err)
123+
}
124+
client := meta.(*config).adminClient.KeyAuths
125+
err = client.Delete(ctx, kong.String(id.ConsumerID), kong.String(id.ID))
126+
127+
if err != nil {
128+
return diag.FromErr(fmt.Errorf("could not delete kong key auth: %v", err))
129+
}
130+
131+
return diags
132+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package kong
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
10+
"github.com/kong/go-kong/kong"
11+
)
12+
13+
func TestAccConsumerKeyAuth(t *testing.T) {
14+
15+
resource.Test(t, resource.TestCase{
16+
Providers: testAccProviders,
17+
CheckDestroy: testAccCheckConsumerKeyAuthDestroy,
18+
Steps: []resource.TestStep{
19+
{
20+
Config: testCreateConsumerKeyAuthConfig,
21+
Check: resource.ComposeTestCheckFunc(
22+
testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"),
23+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "key", "foo"),
24+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "1"),
25+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"),
26+
),
27+
},
28+
{
29+
Config: testUpdateConsumerKeyAuthConfig,
30+
Check: resource.ComposeTestCheckFunc(
31+
testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"),
32+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "key", "foo_updated"),
33+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "2"),
34+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"),
35+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.1", "anotherTag"),
36+
),
37+
},
38+
},
39+
})
40+
}
41+
42+
func TestAccConsumerKeyAuthComputed(t *testing.T) {
43+
44+
resource.Test(t, resource.TestCase{
45+
Providers: testAccProviders,
46+
CheckDestroy: testAccCheckConsumerKeyAuthDestroy,
47+
Steps: []resource.TestStep{
48+
{
49+
Config: testCreateConsumerKeyAuthConfigKeyComputed,
50+
Check: resource.ComposeTestCheckFunc(
51+
testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"),
52+
resource.TestCheckResourceAttrSet("kong_consumer_key_auth.consumer_key_auth", "key"),
53+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "1"),
54+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"),
55+
),
56+
},
57+
{
58+
Config: testUpdateConsumerKeyAuthConfig,
59+
Check: resource.ComposeTestCheckFunc(
60+
testAccCheckConsumerKeyAuthExists("kong_consumer_key_auth.consumer_key_auth"),
61+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "key", "foo_updated"),
62+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.#", "2"),
63+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.0", "myTag"),
64+
resource.TestCheckResourceAttr("kong_consumer_key_auth.consumer_key_auth", "tags.1", "anotherTag"),
65+
),
66+
},
67+
},
68+
})
69+
}
70+
71+
func testAccCheckConsumerKeyAuthDestroy(state *terraform.State) error {
72+
73+
client := testAccProvider.Meta().(*config).adminClient.KeyAuths
74+
75+
resources := getResourcesByType("kong_consumer_key_auth", state)
76+
77+
if len(resources) != 1 {
78+
return fmt.Errorf("expecting only 1 consumer key auth resource found %v", len(resources))
79+
}
80+
81+
id, err := splitConsumerID(resources[0].Primary.ID)
82+
ConsumerKeyAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID))
83+
84+
if !kong.IsNotFoundErr(err) && err != nil {
85+
return fmt.Errorf("error calling get consumer auth by id: %v", err)
86+
}
87+
88+
if ConsumerKeyAuth != nil {
89+
return fmt.Errorf("key auth %s still exists, %+v", id.ID, ConsumerKeyAuth)
90+
}
91+
92+
return nil
93+
}
94+
95+
func testAccCheckConsumerKeyAuthExists(resourceKey string) resource.TestCheckFunc {
96+
97+
return func(s *terraform.State) error {
98+
rs, ok := s.RootModule().Resources[resourceKey]
99+
100+
if !ok {
101+
return fmt.Errorf("not found: %s", resourceKey)
102+
}
103+
104+
if rs.Primary.ID == "" {
105+
return fmt.Errorf("no ID is set")
106+
}
107+
108+
client := testAccProvider.Meta().(*config).adminClient.KeyAuths
109+
id, err := splitConsumerID(rs.Primary.ID)
110+
111+
ConsumerKeyAuth, err := client.Get(context.Background(), kong.String(id.ConsumerID), kong.String(id.ID))
112+
113+
if err != nil {
114+
return err
115+
}
116+
117+
if ConsumerKeyAuth == nil {
118+
return fmt.Errorf("ConsumerKeyAuth with id %v not found", id.ID)
119+
}
120+
121+
return nil
122+
}
123+
}
124+
125+
const testCreateConsumerKeyAuthConfig = `
126+
resource "kong_consumer" "my_consumer" {
127+
username = "User1"
128+
custom_id = "123"
129+
}
130+
131+
resource "kong_plugin" "key_auth_plugin" {
132+
name = "key-auth"
133+
}
134+
135+
resource "kong_consumer_key_auth" "consumer_key_auth" {
136+
consumer_id = "${kong_consumer.my_consumer.id}"
137+
key = "foo"
138+
tags = ["myTag"]
139+
}
140+
`
141+
const testUpdateConsumerKeyAuthConfig = `
142+
resource "kong_consumer" "my_consumer" {
143+
username = "User1"
144+
custom_id = "123"
145+
}
146+
147+
resource "kong_plugin" "key_auth_plugin" {
148+
name = "key-auth"
149+
}
150+
151+
resource "kong_consumer_key_auth" "consumer_key_auth" {
152+
consumer_id = "${kong_consumer.my_consumer.id}"
153+
key = "foo_updated"
154+
tags = ["myTag", "anotherTag"]
155+
}
156+
`
157+
const testCreateConsumerKeyAuthConfigKeyComputed = `
158+
resource "kong_consumer" "my_consumer" {
159+
username = "User1"
160+
custom_id = "123"
161+
}
162+
163+
resource "kong_plugin" "key_auth_plugin" {
164+
name = "key-auth"
165+
}
166+
167+
resource "kong_consumer_key_auth" "consumer_key_auth" {
168+
consumer_id = "${kong_consumer.my_consumer.id}"
169+
tags = ["myTag"]
170+
}
171+
`

kong/utils.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,3 @@ func IDToString(v *string) string {
154154
}
155155
return *v
156156
}
157-
158-
// NilString converts a string to a string pointer,
159-
// or if empty returns nil.
160-
func NilString(str string) *string {
161-
if str == "" {
162-
return nil
163-
} else {
164-
return kong.String(str)
165-
}
166-
}

0 commit comments

Comments
 (0)