feat: support all variations of responseTypes (#104)

This commit is contained in:
Jakub Błaszczyk 2021-12-08 09:25:34 +01:00 committed by GitHub
parent ca4fe77f30
commit a7a2caa606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 61 deletions

17
Dockerfile-kubebuilder Normal file
View File

@ -0,0 +1,17 @@
FROM golang:1.16 as builder
WORKDIR /go/src/app
RUN os=$(go env GOOS) &&\
arch=$(go env GOARCH) &&\
curl -sL https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_${os}_${arch}.tar.gz | tar -xz -C /tmp/ &&\
mv /tmp/kubebuilder_2.3.2_${os}_${arch} /usr/local/kubebuilder &&\
export PATH=$PATH:/usr/local/kubebuilder/bin
COPY . .
RUN make test &&\
make manager
# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:latest
COPY --from=builder /go/src/app/manager .
USER 1000
ENTRYPOINT ["/manager"]

View File

@ -34,12 +34,12 @@ test: generate fmt vet manifests
# Start KIND pseudo-cluster # Start KIND pseudo-cluster
.PHONY: kind-start .PHONY: kind-start
kind-start: kind-start:
GO111MODULE=on go get "sigs.k8s.io/kind@v0.11.1" && kind create cluster kind create cluster
# Stop KIND pseudo-cluster # Stop KIND pseudo-cluster
.PHONY: kind-stop .PHONY: kind-stop
kind-stop: kind-stop:
GO111MODULE=on go get "sigs.k8s.io/kind@v0.11.1" && kind delete cluster kind delete cluster
# Deploy on KIND # Deploy on KIND
# Ensures the controller image is built, deploys the image to KIND cluster along with necessary configuration # Ensures the controller image is built, deploys the image to KIND cluster along with necessary configuration

View File

@ -129,7 +129,7 @@ type OAuth2ClientSpec struct {
// GrantType represents an OAuth 2.0 grant type // GrantType represents an OAuth 2.0 grant type
type GrantType string type GrantType string
// +kubebuilder:validation:Enum=id_token;code;token // +kubebuilder:validation:Enum=id_token;code;token;code token;code id_token;id_token token;code id_token token
// ResponseType represents an OAuth 2.0 response type strings // ResponseType represents an OAuth 2.0 response type strings
type ResponseType string type ResponseType string

View File

@ -101,19 +101,19 @@ func TestCreateAPI(t *testing.T) {
t.Run("by failing if the requested object doesn't meet CRD requirements", func(t *testing.T) { t.Run("by failing if the requested object doesn't meet CRD requirements", func(t *testing.T) {
for desc, modifyClient := range map[string]func(){ for desc, modifyClient := range map[string]func(){
"invalid grant type": func() { created.Spec.GrantTypes = []GrantType{"invalid"} }, "invalid grant type": func() { created.Spec.GrantTypes = []GrantType{"invalid"} },
"invalid response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid"} }, "invalid response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid", "code"} },
"invalid scope": func() { created.Spec.Scope = "" }, "invalid composite response type": func() { created.Spec.ResponseTypes = []ResponseType{"invalid code", "code id_token"} },
"missing secret name": func() { created.Spec.SecretName = "" }, "invalid scope": func() { created.Spec.Scope = "" },
"invalid redirect URI": func() { created.Spec.RedirectURIs = []RedirectURI{"invalid"} }, "missing secret name": func() { created.Spec.SecretName = "" },
"invalid logout redirect URI": func() { created.Spec.PostLogoutRedirectURIs = []RedirectURI{"invalid"} }, "invalid redirect URI": func() { created.Spec.RedirectURIs = []RedirectURI{"invalid"} },
"invalid hydra url": func() { created.Spec.HydraAdmin.URL = "invalid" }, "invalid logout redirect URI": func() { created.Spec.PostLogoutRedirectURIs = []RedirectURI{"invalid"} },
"invalid hydra port high": func() { created.Spec.HydraAdmin.Port = 65536 }, "invalid hydra url": func() { created.Spec.HydraAdmin.URL = "invalid" },
"invalid hydra endpoint": func() { created.Spec.HydraAdmin.Endpoint = "invalid" }, "invalid hydra port high": func() { created.Spec.HydraAdmin.Port = 65536 },
"invalid hydra forwarded proto": func() { created.Spec.HydraAdmin.Endpoint = "invalid" }, "invalid hydra endpoint": func() { created.Spec.HydraAdmin.Endpoint = "invalid" },
"invalid hydra forwarded proto": func() { created.Spec.HydraAdmin.Endpoint = "invalid" },
} { } {
t.Run(fmt.Sprintf("case=%s", desc), func(t *testing.T) { t.Run(fmt.Sprintf("case=%s", desc), func(t *testing.T) {
resetTestClient() resetTestClient()
modifyClient() modifyClient()
createErr = k8sClient.Create(context.TODO(), created) createErr = k8sClient.Create(context.TODO(), created)
@ -121,6 +121,21 @@ func TestCreateAPI(t *testing.T) {
}) })
} }
}) })
t.Run("by creating an object if it passes validation", func(t *testing.T) {
for desc, modifyClient := range map[string]func(){
"single response type": func() { created.Spec.ResponseTypes = []ResponseType{"token", "id_token", "code"} },
"double response type": func() { created.Spec.ResponseTypes = []ResponseType{"id_token token", "code id_token", "code token"} },
"triple response type": func() { created.Spec.ResponseTypes = []ResponseType{"code id_token token"} },
} {
t.Run(fmt.Sprintf("case=%s", desc), func(t *testing.T) {
resetTestClient()
modifyClient()
require.NoError(t, k8sClient.Create(context.TODO(), created))
require.NoError(t, k8sClient.Delete(context.TODO(), created))
})
}
})
}) })
} }

View File

@ -22,14 +22,10 @@ spec:
description: OAuth2Client is the Schema for the oauth2clients API description: OAuth2Client is the Schema for the oauth2clients API
properties: properties:
apiVersion: apiVersion:
description: 'APIVersion defines the versioned schema of this representation description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string type: string
kind: kind:
description: 'Kind is a string value representing the REST resource this description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string type: string
metadata: metadata:
type: object type: object
@ -44,18 +40,15 @@ spec:
type: string type: string
type: array type: array
audience: audience:
description: Audience is a whitelist defining the audiences this client description: Audience is a whitelist defining the audiences this client is allowed to request tokens for
is allowed to request tokens for
items: items:
type: string type: string
type: array type: array
clientName: clientName:
description: ClientName is the human-readable string name of the client description: ClientName is the human-readable string name of the client to be presented to the end-user during authorization.
to be presented to the end-user during authorization.
type: string type: string
grantTypes: grantTypes:
description: GrantTypes is an array of grant types the client is allowed description: GrantTypes is an array of grant types the client is allowed to use.
to use.
items: items:
description: GrantType represents an OAuth 2.0 grant type description: GrantType represents an OAuth 2.0 grant type
enum: enum:
@ -68,31 +61,22 @@ spec:
minItems: 1 minItems: 1
type: array type: array
hydraAdmin: hydraAdmin:
description: HydraAdmin is the optional configuration to use for managing description: HydraAdmin is the optional configuration to use for managing this client
this client
properties: properties:
endpoint: endpoint:
description: Endpoint is the endpoint for the hydra instance on description: Endpoint is the endpoint for the hydra instance on which to set up the client. This value will override the value provided to `--endpoint` (defaults to `"/clients"` in the application)
which to set up the client. This value will override the value
provided to `--endpoint` (defaults to `"/clients"` in the application)
pattern: (^$|^/.*) pattern: (^$|^/.*)
type: string type: string
forwardedProto: forwardedProto:
description: ForwardedProto overrides the `--forwarded-proto` description: ForwardedProto overrides the `--forwarded-proto` flag. The value "off" will force this to be off even if `--forwarded-proto` is specified
flag. The value "off" will force this to be off even if `--forwarded-proto`
is specified
pattern: (^$|https?|off) pattern: (^$|https?|off)
type: string type: string
port: port:
description: Port is the port for the hydra instance on which description: Port is the port for the hydra instance on which to set up the client. This value will override the value provided to `--hydra-port`
to set up the client. This value will override the value provided
to `--hydra-port`
maximum: 65535 maximum: 65535
type: integer type: integer
url: url:
description: URL is the URL for the hydra instance on which to description: URL is the URL for the hydra instance on which to set up the client. This value will override the value provided to `--hydra-url`
set up the client. This value will override the value provided
to `--hydra-url`
maxLength: 64 maxLength: 64
pattern: (^$|^https?://.*) pattern: (^$|^https?://.*)
type: string type: string
@ -103,44 +87,41 @@ spec:
type: object type: object
x-kubernetes-preserve-unknown-fields: true x-kubernetes-preserve-unknown-fields: true
postLogoutRedirectUris: postLogoutRedirectUris:
description: PostLogoutRedirectURIs is an array of the post logout description: PostLogoutRedirectURIs is an array of the post logout redirect URIs allowed for the application
redirect URIs allowed for the application
items: items:
description: RedirectURI represents a redirect URI for the client description: RedirectURI represents a redirect URI for the client
pattern: \w+:/?/?[^\s]+ pattern: \w+:/?/?[^\s]+
type: string type: string
type: array type: array
redirectUris: redirectUris:
description: RedirectURIs is an array of the redirect URIs allowed description: RedirectURIs is an array of the redirect URIs allowed for the application
for the application
items: items:
description: RedirectURI represents a redirect URI for the client description: RedirectURI represents a redirect URI for the client
pattern: \w+:/?/?[^\s]+ pattern: \w+:/?/?[^\s]+
type: string type: string
type: array type: array
responseTypes: responseTypes:
description: ResponseTypes is an array of the OAuth 2.0 response type description: ResponseTypes is an array of the OAuth 2.0 response type strings that the client can use at the authorization endpoint.
strings that the client can use at the authorization endpoint.
items: items:
description: ResponseType represents an OAuth 2.0 response type description: ResponseType represents an OAuth 2.0 response type strings
strings
enum: enum:
- id_token - id_token
- code - code
- token - token
- code token
- code id_token
- id_token token
- code id_token token
type: string type: string
maxItems: 3 maxItems: 3
minItems: 1 minItems: 1
type: array type: array
scope: scope:
description: Scope is a string containing a space-separated list of description: Scope is a string containing a space-separated list of scope values (as described in Section 3.3 of OAuth 2.0 [RFC6749]) that the client can use when requesting access tokens.
scope values (as described in Section 3.3 of OAuth 2.0 [RFC6749])
that the client can use when requesting access tokens.
pattern: ([a-zA-Z0-9\.\*]+\s?)+ pattern: ([a-zA-Z0-9\.\*]+\s?)+
type: string type: string
secretName: secretName:
description: SecretName points to the K8s secret that contains this description: SecretName points to the K8s secret that contains this client's ID and password
client's ID and password
maxLength: 253 maxLength: 253
minLength: 1 minLength: 1
pattern: '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*' pattern: '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*'
@ -157,8 +138,7 @@ spec:
- client_secret_post - client_secret_post
- private_key_jwt - private_key_jwt
- none - none
description: Indication which authentication method shoud be used description: Indication which authentication method shoud be used for the token endpoint
for the token endpoint
type: string type: string
required: required:
- grantTypes - grantTypes
@ -169,17 +149,14 @@ spec:
description: OAuth2ClientStatus defines the observed state of OAuth2Client description: OAuth2ClientStatus defines the observed state of OAuth2Client
properties: properties:
observedGeneration: observedGeneration:
description: ObservedGeneration represents the most recent generation description: ObservedGeneration represents the most recent generation observed by the daemon set controller.
observed by the daemon set controller.
format: int64 format: int64
type: integer type: integer
reconciliationError: reconciliationError:
description: ReconciliationError represents an error that occurred description: ReconciliationError represents an error that occurred during the reconciliation process
during the reconciliation process
properties: properties:
description: description:
description: Description is the description of the reconciliation description: Description is the description of the reconciliation error
error
type: string type: string
statusCode: statusCode:
description: Code is the status code of the reconciliation error description: Code is the status code of the reconciliation error

View File

@ -13,6 +13,10 @@ spec:
- id_token - id_token
- code - code
- token - token
- code token
- code id_token
- id_token token
- code id_token token
scope: "read write" scope: "read write"
secretName: my-secret-123 secretName: my-secret-123
# these are optional # these are optional