Skip to content

Commit

Permalink
APIGW NS JWT Auth (#2962)
Browse files Browse the repository at this point in the history
* NET-4978: New CRDs for GW JWT Auth (#2734)

* Added CRDs for gateway policy and httproute auth filter

* Added bats tests

* Correctly configured http route auth filter extension

* Small docs update for operator-sdk usage

* updated docs a bit, added gateway policy CRD

* removed extra crd, updated bats tests

* Added changelog

* Added periods for consistency

* Revert unnecessary changes

* make jwt requirement optional

* Updated jwt config to be optional to allow for other auth types

* Rename HTTPRouteAuthFilter to RouteAuthFilter

* Fix typo for omitempty

* finish httprouteauthfilters rename to routeauthfilters

* Added target reference for gateway policies

* Add period to sentence for linter

* Rename APIGatewayJWT* fields to GatewayJWT* and fixed spots of renaming
of HTTPRouteAuthFilter to RouteAuthFilter

* Gateway policy translation NET 4980 (#2835)

* squash

* reset crd-gatewaypolicies

* reset

* reset

* fix lint issues

* fix nil pointer issue

* checkpoint

* change to resourseref key

* update to pull all policies

* add nil checks

* more nil pointer checks for defensice programing

* fix lint issue

* delete comment

* add unit test, fix add function

* Update control-plane/api-gateway/common/translation.go

Co-authored-by: Thomas Eckert <[email protected]>

* Translate HTTPAuthFilter onto HTTPRoute (#2836)

* Add function

* Add RouteAuthFilterKind export

* Add ServicesForRoute function

* Start adding translateHTTPRouteAuth

* Added translation filter to existing filter processing

* Split out formatting into subfunctions

* Remove original function

* Remove ServicesForRoute

* Change httprouteauthfilter to routeauthfilter

* Reuse GatewayJWT type for Routes

* Match Sarah's style for translation functions

* Start adding filter tests

* Wrap up test for filters

* Uncomment other tests

* Use existing v1alpha1 import for group

* Remove old make* function

* Use ConvertSliceFunc

* Fix group in translation_test

* Manually un-diff CRDs

* cleanup

* cleanup

* clean up

* update index function

---------

Co-authored-by: Thomas Eckert <[email protected]>

* Added validating webhook for gateway policy (#2912)

* Added validating webhook for gateway policy

* Change denied message to provide more information to the operator

* [APIGW] Add comparison of gateway policies to diffing logic (#2939)

* Fix bug in comparison of gateway policies

* fix fmting

* Added gateway equal test

* Finished adding tests and refactored to use slices convencience
functions

* Reconcile Route Auth Filter changes (#2954)

* Group indices by resource

* Add index for HTTPRoutes referencing RouteAuthFilters

* Add watch for HTTPRoutes referencing RouteAuthFilters

* Add permissions to connect-inject clusterrole

* Compare JWT filters for equality

* Add RouteAuthFilter to resource translator

* [NET-5017] APIGW Status Conditions for Gateway for JWT/Reconcile on JWTProvider Changes (#2950)

* Added watches and status condition on gateway listeners for JWT
validation

* Only append errors if they're non-nil

* Added tests for validating jwt on listener and for adding/retrieving jwt
from resource map

* fix fmting

* Clean up from PR review

* Use two value form of map access

* Rename function

* clean up from PR review

* [NET-5017] APIGW Status Conditions for Gateway Policies (#2955)

* Adding status conditions for gw policy

* Fixed issue where status was not being propagated for policies

* Moved code to correct places

* Revert formatting

* Cleaned up error creation, added validation tests

* Added results tests, updated binding test

* Updates from PR review: clean up comments/appends, use correct
conditions for defaults

* [NET-5017] APIGW Status Conditions for RouteAuthFilter and Routes wrt JWT (#2961)

* NET-4978: New CRDs for GW JWT Auth (#2734)

* Added CRDs for gateway policy and httproute auth filter

* Added bats tests

* Correctly configured http route auth filter extension

* Small docs update for operator-sdk usage

* updated docs a bit, added gateway policy CRD

* removed extra crd, updated bats tests

* Added changelog

* Added periods for consistency

* Revert unnecessary changes

* make jwt requirement optional

* Updated jwt config to be optional to allow for other auth types

* Rename HTTPRouteAuthFilter to RouteAuthFilter

* Fix typo for omitempty

* finish httprouteauthfilters rename to routeauthfilters

* Added target reference for gateway policies

* Add period to sentence for linter

* Rename APIGatewayJWT* fields to GatewayJWT* and fixed spots of renaming
of HTTPRouteAuthFilter to RouteAuthFilter

* Gateway policy translation NET 4980 (#2835)

* squash

* reset crd-gatewaypolicies

* reset

* reset

* fix lint issues

* fix nil pointer issue

* checkpoint

* change to resourseref key

* update to pull all policies

* add nil checks

* more nil pointer checks for defensice programing

* fix lint issue

* delete comment

* add unit test, fix add function

* Update control-plane/api-gateway/common/translation.go

Co-authored-by: Thomas Eckert <[email protected]>

* Translate HTTPAuthFilter onto HTTPRoute (#2836)

* Add function

* Add RouteAuthFilterKind export

* Add ServicesForRoute function

* Start adding translateHTTPRouteAuth

* Added translation filter to existing filter processing

* Split out formatting into subfunctions

* Remove original function

* Remove ServicesForRoute

* Change httprouteauthfilter to routeauthfilter

* Reuse GatewayJWT type for Routes

* Match Sarah's style for translation functions

* Start adding filter tests

* Wrap up test for filters

* Uncomment other tests

* Use existing v1alpha1 import for group

* Remove old make* function

* Use ConvertSliceFunc

* Fix group in translation_test

* Manually un-diff CRDs

* cleanup

* cleanup

* clean up

* update index function

---------

Co-authored-by: Thomas Eckert <[email protected]>

* Added status conditions for JWT for auth filters and for routes

* Extract function

* Use more generic error for invalid filter

* Re-run ctrl-manifests with correct controller-generate version

* Clean up from pr review

* gofmt

---------

Co-authored-by: sarahalsmiller <[email protected]>
Co-authored-by: Thomas Eckert <[email protected]>

* Added changelog

* clean up some renames from httprouteauthfilter -> routeauthfilter

* Fix broken webhook test, added new test

---------

Co-authored-by: sarahalsmiller <[email protected]>
Co-authored-by: Thomas Eckert <[email protected]>
  • Loading branch information
3 people authored Sep 15, 2023
1 parent 60d09e2 commit 2d03f3e
Show file tree
Hide file tree
Showing 46 changed files with 6,513 additions and 244 deletions.
3 changes: 3 additions & 0 deletions .changelog/2962.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```releast-note:feature
api-gateway: (Consul Enterprise) Add JWT authentication and authorization for API Gateway and HTTPRoutes.
```
88 changes: 44 additions & 44 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
1. [Running linters locally](#running-linters-locally)
1. [Rebasing contributions against main](#rebasing-contributions-against-main)
1. [Creating a new CRD](#creating-a-new-crd)
1. [The Structs](#the-structs)
1. [The Structs](#the-structs)
1. [Spec Methods](#spec-methods)
1. [Spec Tests](#spec-tests)
1. [Controller](#controller)
Expand All @@ -31,13 +31,13 @@

### Building and running `consul-k8s-control-plane`

To build and install the control plane binary `consul-k8s-control-plane` locally, Go version 1.17.0+ is required.
To build and install the control plane binary `consul-k8s-control-plane` locally, Go version 1.17.0+ is required.
You will also need to install the Docker engine:

- [Docker for Mac](https://docs.docker.com/engine/installation/mac/)
- [Docker for Windows](https://docs.docker.com/engine/installation/windows/)
- [Docker for Linux](https://docs.docker.com/engine/installation/linux/ubuntulinux/)

Install [gox](https://github.com/mitchellh/gox) (v1.14+). For Mac and Linux:
```bash
brew install gox
Expand Down Expand Up @@ -102,7 +102,7 @@ controller:
enabled: true
```
Run a `helm install` from the project root directory to target your dev version of the Helm chart.
Run a `helm install` from the project root directory to target your dev version of the Helm chart.

```shell
helm install consul --create-namespace -n consul -f ./values.dev.yaml ./charts/consul
Expand All @@ -125,7 +125,7 @@ consul-k8s version

### Making changes to consul-k8s

The first step to making changes is to fork Consul K8s. Afterwards, the easiest way
The first step to making changes is to fork Consul K8s. Afterwards, the easiest way
to work on the fork is to set it as a remote of the Consul K8s project:

1. Rename the existing remote's name: `git remote rename origin upstream`.
Expand Down Expand Up @@ -164,7 +164,7 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
## Creating a new CRD

### The Structs
1. Run the generate command:
1. Run the generate command from the `control-plane` directory: (installation instructions for `operator-sdk` found [here](https://sdk.operatorframework.io/docs/installation/):
```bash
operator-sdk create api --group consul --version v1alpha1 --kind IngressGateway --controller --namespaced=true --make=false --resource=true
```
Expand All @@ -173,37 +173,37 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
func init() {
SchemeBuilder.Register(&IngressGateway{}, &IngressGatewayList{})
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// IngressGateway is the Schema for the ingressgateways API
type IngressGateway struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec IngressGatewaySpec `json:"spec,omitempty"`
Status IngressGatewayStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true

// IngressGatewayList contains a list of IngressGateway
type IngressGatewayList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []IngressGateway `json:"items"`
}

// IngressGatewaySpec defines the desired state of IngressGateway
type IngressGatewaySpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file

// Foo is an example field of IngressGateway. Edit IngressGateway_types.go to remove/update
Foo string `json:"foo,omitempty"`
}

// IngressGatewayStatus defines the observed state of IngressGateway
type IngressGatewayStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
Expand All @@ -225,7 +225,7 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
type IngressGateway struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec IngressGatewaySpec `json:"spec,omitempty"`
- Status IngressGatewayStatus `json:"status,omitempty"`
+ Status `json:"status,omitempty"`
Expand All @@ -235,7 +235,7 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
1. Copy the top-level fields over into the `Spec` struct except for
`Kind`, `Name`, `Namespace`, `Partition`, `Meta`, `CreateIndex` and `ModifyIndex`. In this
example, the top-level fields remaining are `TLS` and `Listeners`:

```go
// IngressGatewaySpec defines the desired state of IngressGateway
type IngressGatewaySpec struct {
Expand All @@ -261,8 +261,8 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
automatically stub out all the methods by using Code -> Generate -> IngressGateway -> ConfigEntryResource.
1. Use existing implementations of other types to implement the methods. We have to
copy their code because we can't use a common struct that implements the methods
because that messes up the CRD code generation.
because that messes up the CRD code generation.

You should be able to follow the other "normal" types. The non-normal types
are `ServiceIntention` and `ProxyDefault` because they have special behaviour
around being global or their spec not matching up with Consul's directly.
Expand All @@ -273,7 +273,7 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
1. For `Validate`, we again follow the pattern of implementing the method on
each sub-struct. You'll need to read the Consul documentation to understand
what validation needs to be done.

Things to keep in mind:
1. Re-use the `sliceContains` and `notInSliceMessage` helper methods where applicable.
1. If the invalid field is an entire struct, encode as json (look for `asJSON` for an example).
Expand Down Expand Up @@ -333,7 +333,7 @@ rebase the branch on main, fixing any conflicts along the way before the code ca
1. `TestConfigEntryControllers_doesNotCreateUnownedConfigEntry`
1. `TestConfigEntryControllers_doesNotDeleteUnownedConfig`
1. Note: we don't add tests to `configentry_controller_ent_test.go` because we decided
it's too much duplication and the controllers are already properly exercised in the oss tests.
it's too much duplication and the controllers are already properly exercised in the oss tests.

### Webhook
1. Copy an existing webhook to `control-plane/api/v1alpha/ingressgateway_webhook.go`
Expand Down Expand Up @@ -507,7 +507,7 @@ a token named `foo`.
```
* Add `if` statement in `Run` to create your token (follow placement of other tokens).
You'll need to decide if you need a local token (use `createLocalACL()`) or a global token (use `createGlobalACL()`).

```go
if c.flagCreateFooToken {
err := c.createLocalACL("foo", fooRules, consulDC, isPrimary, consulClient)
Expand Down Expand Up @@ -588,7 +588,7 @@ The acceptance tests require a Kubernetes cluster with a configured `kubectl`.
```bash
brew install python-yq
```
* [Helm 3](https://helm.sh) (Currently, must use v3.8.0+.)
* [Helm 3](https://helm.sh) (Currently, must use v3.8.0+.)
```bash
brew install kubernetes-helm
```
Expand Down Expand Up @@ -617,7 +617,7 @@ To run a specific test by name use the `--filter` flag:
bats ./charts/consul/test/unit/<filename>.bats --filter "my test name"

#### Acceptance Tests
##### Pre-requisites
##### Pre-requisites
* [gox](https://github.com/mitchellh/gox) (v1.14+)
```bash
brew install gox
Expand All @@ -629,7 +629,7 @@ To run the acceptance tests:

cd acceptance/tests
go test ./... -p 1

The above command will run all tests that can run against a single Kubernetes cluster,
using the current context set in your kubeconfig locally.

Expand Down Expand Up @@ -689,7 +689,7 @@ Changes to the Helm chart should be accompanied by appropriate unit tests.

#### Formatting

- Put tests in the test file in the same order as the variables appear in the `values.yaml`.
- Put tests in the test file in the same order as the variables appear in the `values.yaml`.
- Start tests for a chart value with a header that says what is being tested, like this:
```
#--------------------------------------------------------------------
Expand All @@ -710,8 +710,8 @@ In all of the tests in this repo, the base command being run is [helm template](
In this way, we're able to test that the various conditionals in the templates render as we would expect.

Each test defines the files that should be rendered using the `-x` flag, then it might adjust chart values by adding `--set` flags as well.
The output from this `helm template` command is then piped to [yq](https://pypi.org/project/yq/).
`yq` allows us to pull out just the information we're interested in, either by referencing its position in the yaml file directly or giving information about it (like its length).
The output from this `helm template` command is then piped to [yq](https://pypi.org/project/yq/).
`yq` allows us to pull out just the information we're interested in, either by referencing its position in the yaml file directly or giving information about it (like its length).
The `-r` flag can be used with `yq` to return a raw string instead of a quoted one which is especially useful when looking for an exact match.

The test passes or fails based on the conditional at the end that is in square brackets, which is a comparison of our expected value and the output of `helm template` piped to `yq`.
Expand Down Expand Up @@ -786,11 +786,11 @@ Here are some examples of common test patterns:
cd `chart_dir`
assert_empty helm template \
-s templates/sync-catalog-deployment.yaml \
.
.
}
```
Here we are using the `assert_empty` helper command.

### Writing Acceptance Tests

If you are adding a feature that fits thematically with one of the existing test suites,
Expand Down Expand Up @@ -831,9 +831,9 @@ you need to handle that in the `TestMain` function.

```go
func TestMain(m *testing.M) {
// First, create a new suite so that all flags are parsed.
// First, create a new suite so that all flags are parsed.
suite = framework.NewSuite(m)
// Run the suite only if our example feature test flag is set.
if suite.Config().EnableExampleFeature {
os.Exit(suite.Run())
Expand Down Expand Up @@ -866,16 +866,16 @@ func TestExample(t *testing.T) {
helmValues := map[string]string{
"exampleFeature.enabled": "true",
}
// Generate a random name for this test.
// Generate a random name for this test.
releaseName := helpers.RandomName()
// Create a new Consul cluster object.
consulCluster := framework.NewHelmCluster(t, helmValues, ctx, cfg, releaseName)
// Create the Consul cluster with Helm.
consulCluster.Create(t)
// Make test assertions.
}
```
Expand Down Expand Up @@ -981,7 +981,7 @@ Any given test can be run either through GoLand or another IDE, or via command l
To run all of the connect tests from command line:
```shell
$ cd acceptance/tests
$ go test ./connect/... -v -p 1 -timeout 2h -failfast -use-kind -no-cleanup-on-failure -kubecontext=kind-dc1 -secondary-kubecontext=kind-dc2 -enable-enterprise -enable-multi-cluster -debug-directory=/tmp/debug -consul-k8s-image=kyleschochenmaier/consul-k8s-acls
$ go test ./connect/... -v -p 1 -timeout 2h -failfast -use-kind -no-cleanup-on-failure -kubecontext=kind-dc1 -secondary-kubecontext=kind-dc2 -enable-enterprise -enable-multi-cluster -debug-directory=/tmp/debug -consul-k8s-image=kyleschochenmaier/consul-k8s-acls
```

When running from command line a few things are important:
Expand Down Expand Up @@ -1129,25 +1129,25 @@ Certificate:
X509v3 Subject Alternative Name:
DNS:pri-1dchdli.vault.ca.34a76791.consul, URI:spiffe://34a76791-b9b2-b93e-b0e4-1989ed11a28e.consul
<snip>
```
```

---

## Helm Reference Docs

The Helm reference docs (https://www.consul.io/docs/k8s/helm) are automatically
generated from our `values.yaml` file.

### Generating Helm Reference Docs

To generate the docs and update the `helm.mdx` file:

1. Fork `hashicorp/consul` (https://github.com/hashicorp/consul) on GitHub.
1. Clone your fork:
```shell-session
git clone https://github.com/<your-username>/consul.git
```
1. Change directory into your `consul-k8s` repo:
1. Change directory into your `consul-k8s` repo:
```shell-session
cd /path/to/consul-k8s
```
Expand Down Expand Up @@ -1216,11 +1216,11 @@ manage. One such example is the Gateway API CRDs which we use to configure API G
Networking.

To pull external CRDs into our Helm chart and make sure they get installed, we generate their configuration using
[Kustomize](https://kustomize.io/) which can pull in Kubernetes config from external sources. We split these
[Kustomize](https://kustomize.io/) which can pull in Kubernetes config from external sources. We split these
generated CRDs into individual files and store them in the `charts/consul/templates` directory.

If you need to update the external CRDs we depend on, or add to them, you can do this by editing the
[control-plane/config/crd/external/kustomization.yaml](/control-plane/config/crd/external/kustomization.yaml) file.
If you need to update the external CRDs we depend on, or add to them, you can do this by editing the
[control-plane/config/crd/external/kustomization.yaml](/control-plane/config/crd/external/kustomization.yaml) file.
Once modified, running

```bash
Expand Down Expand Up @@ -1261,7 +1261,7 @@ Some common values are:
- `control-plane`: related to control-plane functionality
- `helm`: related to the charts module and any files, yaml, go, etc. therein

There may be cases where a `code area` doesn't make sense (i.e. addressing a Go CVE). In these
There may be cases where a `code area` doesn't make sense (i.e. addressing a Go CVE). In these
cases it is okay not to provide a `code area`.

For more examples, look in the [`.changelog/`](../.changelog) folder for existing changelog entries.
Expand Down
6 changes: 6 additions & 0 deletions charts/consul/templates/connect-inject-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ rules:
- controlplanerequestlimits
- routeretryfilters
- routetimeoutfilters
- routeauthfilters
- gatewaypolicies
{{- if .Values.global.peering.enabled }}
- peeringacceptors
- peeringdialers
{{- end }}
- jwtproviders
- routeauthfilters
verbs:
- create
- delete
Expand Down Expand Up @@ -63,6 +66,8 @@ rules:
- peeringdialers/status
{{- end }}
- jwtproviders/status
- routeauthfilters/status
- gatewaypolicies/status
verbs:
- get
- patch
Expand Down Expand Up @@ -107,6 +112,7 @@ rules:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
- validatingwebhookconfigurations
verbs:
- get
- list
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{{- if (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled)) }}
# The ValidatingWebhookConfiguration to enable the Connect injector.
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "consul.name" . }}
chart: {{ template "consul.chart" . }}
heritage: {{ .Release.Service }}
release: {{ .Release.Name }}
component: connect-injector
webhooks:
- name: validate-gatewaypolicy.consul.hashicorp.com
matchPolicy: Equivalent
rules:
- operations: [ "CREATE" , "UPDATE" ]
apiGroups: [ "consul.hashicorp.com" ]
apiVersions: [ "v1alpha1" ]
resources: [ "gatewaypolicies" ]
failurePolicy: Fail
sideEffects: None
admissionReviewVersions:
- v1
clientConfig:
service:
name: {{ template "consul.fullname" . }}-connect-injector
namespace: {{ .Release.Namespace }}
path: /validate-v1alpha1-gatewaypolicy
{{- end }}
Loading

0 comments on commit 2d03f3e

Please sign in to comment.