-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
NET-4984: Update APIGW Config Entries for JWT Auth #18366
Changes from 9 commits
ce4d50e
8c3a07a
816b47f
2879b99
20cfcf9
7c21848
0bf2f5e
ce2aacc
886a0c5
010279a
ce5dc85
b223c1a
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,3 @@ | ||
```release-note:feature | ||
config-entry(api-gateway): (Enterprise only) Add GatewayPolicy to APIGateway Config Entry listeners | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
//go:build !consulent | ||
// +build !consulent | ||
|
||
package structs | ||
|
||
// APIGatewayJWTRequirement holds the list of JWT providers to be verified against | ||
type APIGatewayJWTRequirement struct{} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package structs | ||
|
||
// DeepCopy generates a deep copy of *APIGatewayJWTRequirement | ||
func (o *APIGatewayJWTRequirement) DeepCopy() *APIGatewayJWTRequirement { | ||
return new(APIGatewayJWTRequirement) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -348,3 +348,150 @@ func TestAPI_ConfigEntries_TerminatingGateway(t *testing.T) { | |
_, _, err = configEntries.Get(TerminatingGateway, "foo", nil) | ||
require.Error(t, err) | ||
} | ||
|
||
func TestAPI_ConfigEntries_APIGateway(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. Good add, m8! |
||
t.Parallel() | ||
c, s := makeClient(t) | ||
defer s.Stop() | ||
|
||
configEntries := c.ConfigEntries() | ||
listener1 := APIGatewayListener{ | ||
Name: "listener1", | ||
Hostname: "host.com", | ||
Port: 3360, | ||
Protocol: "http", | ||
} | ||
|
||
listener2 := APIGatewayListener{ | ||
Name: "listener2", | ||
Hostname: "host2.com", | ||
Port: 3362, | ||
Protocol: "http", | ||
} | ||
|
||
apigw1 := &APIGatewayConfigEntry{ | ||
Kind: APIGateway, | ||
Name: "foo", | ||
Meta: map[string]string{ | ||
"foo": "bar", | ||
"gir": "zim", | ||
}, | ||
Listeners: []APIGatewayListener{listener1}, | ||
} | ||
|
||
apigw2 := &APIGatewayConfigEntry{ | ||
Kind: APIGateway, | ||
Name: "bar", | ||
Listeners: []APIGatewayListener{listener2}, | ||
} | ||
|
||
// set it | ||
_, wm, err := configEntries.Set(apigw1, nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, wm) | ||
require.NotEqual(t, 0, wm.RequestTime) | ||
|
||
// also set the second one | ||
_, wm, err = configEntries.Set(apigw2, nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, wm) | ||
require.NotEqual(t, 0, wm.RequestTime) | ||
|
||
// get it | ||
entry, qm, err := configEntries.Get(APIGateway, "foo", nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, qm) | ||
require.NotEqual(t, 0, qm.RequestTime) | ||
|
||
// verify it | ||
readGW, ok := entry.(*APIGatewayConfigEntry) | ||
require.True(t, ok) | ||
require.Equal(t, apigw1.Kind, readGW.Kind) | ||
require.Equal(t, apigw1.Name, readGW.Name) | ||
require.Equal(t, apigw1.Meta, readGW.Meta) | ||
require.Equal(t, apigw1.Meta, readGW.GetMeta()) | ||
|
||
// update it | ||
apigw1.Listeners = []APIGatewayListener{ | ||
listener1, | ||
{ | ||
Name: "listener3", | ||
Hostname: "host3.com", | ||
Port: 3363, | ||
Protocol: "http", | ||
}, | ||
} | ||
|
||
// CAS fail | ||
written, _, err := configEntries.CAS(apigw1, 0, nil) | ||
require.NoError(t, err) | ||
require.False(t, written) | ||
|
||
// CAS success | ||
written, wm, err = configEntries.CAS(apigw1, readGW.ModifyIndex, nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, wm) | ||
require.NotEqual(t, 0, wm.RequestTime) | ||
require.True(t, written) | ||
|
||
// re-setting should not yield an error | ||
_, wm, err = configEntries.Set(apigw1, nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, wm) | ||
require.NotEqual(t, 0, wm.RequestTime) | ||
|
||
apigw2.Listeners = []APIGatewayListener{ | ||
listener2, | ||
{ | ||
Name: "listener4", | ||
Hostname: "host4.com", | ||
Port: 3364, | ||
Protocol: "http", | ||
}, | ||
} | ||
|
||
_, wm, err = configEntries.Set(apigw2, nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, wm) | ||
require.NotEqual(t, 0, wm.RequestTime) | ||
|
||
// list them | ||
entries, qm, err := configEntries.List(APIGateway, nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, qm) | ||
require.NotEqual(t, 0, qm.RequestTime) | ||
require.Len(t, entries, 2) | ||
|
||
for _, entry = range entries { | ||
switch entry.GetName() { | ||
case "foo": | ||
// this also verifies that the update value was persisted and | ||
// the updated values are seen | ||
readGW, ok = entry.(*APIGatewayConfigEntry) | ||
require.True(t, ok) | ||
require.Equal(t, apigw1.Kind, readGW.Kind) | ||
require.Equal(t, apigw1.Name, readGW.Name) | ||
require.Len(t, readGW.Listeners, 2) | ||
|
||
require.Equal(t, apigw1.Listeners, readGW.Listeners) | ||
case "bar": | ||
readGW, ok = entry.(*APIGatewayConfigEntry) | ||
require.True(t, ok) | ||
require.Equal(t, apigw2.Kind, readGW.Kind) | ||
require.Equal(t, apigw2.Name, readGW.Name) | ||
require.Len(t, readGW.Listeners, 2) | ||
|
||
require.Equal(t, apigw2.Listeners, readGW.Listeners) | ||
} | ||
} | ||
|
||
// delete it | ||
wm, err = configEntries.Delete(APIGateway, "foo", nil) | ||
require.NoError(t, err) | ||
require.NotNil(t, wm) | ||
require.NotEqual(t, 0, wm.RequestTime) | ||
|
||
// verify deletion | ||
_, _, err = configEntries.Get(APIGateway, "foo", nil) | ||
require.Error(t, err) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,12 +8,14 @@ import ( | |
"fmt" | ||
"io" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/mitchellh/mapstructure" | ||
|
||
"github.com/hashicorp/consul/api" | ||
"github.com/hashicorp/consul/lib/decode" | ||
"github.com/hashicorp/go-multierror" | ||
"github.com/mitchellh/mapstructure" | ||
) | ||
|
||
func loadFromFile(path string) (string, error) { | ||
|
@@ -124,13 +126,19 @@ func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) { | |
} | ||
|
||
for _, k := range md.Unused { | ||
switch k { | ||
case "kind", "Kind": | ||
switch { | ||
case strings.ToLower(k) == "kind": | ||
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. I changed this up so that the error messaging would be the same whether doing a |
||
// The kind field is used to determine the target, but doesn't need | ||
// to exist on the target. | ||
continue | ||
|
||
case strings.HasSuffix(strings.ToLower(k), "namespace"): | ||
err = multierror.Append(err, fmt.Errorf("invalid config key %q, namespaces are a consul enterprise feature", k)) | ||
case strings.Contains(strings.ToLower(k), "jwt"): | ||
err = multierror.Append(err, fmt.Errorf("invalid config key %q, api-gateway jwt validation is a consul enterprise feature", k)) | ||
default: | ||
err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) | ||
} | ||
err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) | ||
} | ||
if err != nil { | ||
return nil, err | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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.
so for this I'm hoping that my PR for globusdigital/deep-copy#33 gets merged which will let us generate
DeepCopy
methods with build tags for both ent and oss without conflictThere 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.
if this doesn't I'll hand write the deep copy methods for now
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.
manually wrote the deep copy methods for the time being, if that PR gets merged I'll update this to use the generated methods with build tags