OIDCClient watcher controller updates based on PR feedback
This commit is contained in:
parent
43a76648d5
commit
93939ccbd8
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.17/README.adoc
generated
7
generated/1.17/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-17-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.18/README.adoc
generated
7
generated/1.18/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-18-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.19/README.adoc
generated
7
generated/1.19/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-19-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.20/README.adoc
generated
7
generated/1.20/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-20-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.21/README.adoc
generated
7
generated/1.21/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-21-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.22/README.adoc
generated
7
generated/1.22/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-22-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-22-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-22-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-22-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.23/README.adoc
generated
7
generated/1.23/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-23-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-23-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-23-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-23-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
7
generated/1.24/README.adoc
generated
7
generated/1.24/README.adoc
generated
@ -724,7 +724,7 @@ OIDCClient describes the configuration of an OIDC client.
|
|||||||
[id="{anchor_prefix}-go-pinniped-dev-generated-1-24-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
[id="{anchor_prefix}-go-pinniped-dev-generated-1-24-apis-supervisor-config-v1alpha1-oidcclientspec"]
|
||||||
==== OIDCClientSpec
|
==== OIDCClientSpec
|
||||||
|
|
||||||
OIDCClientSpec is a struct that describes an OIDC Client.
|
OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
|
|
||||||
.Appears In:
|
.Appears In:
|
||||||
****
|
****
|
||||||
@ -755,8 +755,9 @@ OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
|||||||
[cols="25a,75a", options="header"]
|
[cols="25a,75a", options="header"]
|
||||||
|===
|
|===
|
||||||
| Field | Description
|
| Field | Description
|
||||||
| *`phase`* __OIDCClientPhase__ | Phase summarizes the overall status of the OIDCClient.
|
| *`phase`* __OIDCClientPhase__ | phase summarizes the overall status of the OIDCClient.
|
||||||
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-24-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | Represents the observations of an OIDCClient's current state.
|
| *`conditions`* __xref:{anchor_prefix}-go-pinniped-dev-generated-1-24-apis-supervisor-config-v1alpha1-condition[$$Condition$$] array__ | conditions represent the observations of an OIDCClient's current state.
|
||||||
|
| *`totalClientSecrets`* __integer__ | totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|===
|
|===
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -117,8 +117,8 @@ spec:
|
|||||||
description: Status of the OIDC client.
|
description: Status of the OIDC client.
|
||||||
properties:
|
properties:
|
||||||
conditions:
|
conditions:
|
||||||
description: Represents the observations of an OIDCClient's current
|
description: conditions represent the observations of an OIDCClient's
|
||||||
state.
|
current state.
|
||||||
items:
|
items:
|
||||||
description: Condition status of a resource (mirrored from the metav1.Condition
|
description: Condition status of a resource (mirrored from the metav1.Condition
|
||||||
type added in Kubernetes 1.19). In a future API version we can
|
type added in Kubernetes 1.19). In a future API version we can
|
||||||
@ -185,12 +185,18 @@ spec:
|
|||||||
x-kubernetes-list-type: map
|
x-kubernetes-list-type: map
|
||||||
phase:
|
phase:
|
||||||
default: Pending
|
default: Pending
|
||||||
description: Phase summarizes the overall status of the OIDCClient.
|
description: phase summarizes the overall status of the OIDCClient.
|
||||||
enum:
|
enum:
|
||||||
- Pending
|
- Pending
|
||||||
- Ready
|
- Ready
|
||||||
- Error
|
- Error
|
||||||
type: string
|
type: string
|
||||||
|
totalClientSecrets:
|
||||||
|
description: totalClientSecrets is the current number of client secrets
|
||||||
|
that are detected for this OIDCClient.
|
||||||
|
type: integer
|
||||||
|
required:
|
||||||
|
- totalClientSecrets
|
||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- spec
|
- spec
|
||||||
|
@ -27,7 +27,7 @@ type GrantType string
|
|||||||
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
// +kubebuilder:validation:Enum="openid";"offline_access";"username";"groups";"pinniped:request-audience"
|
||||||
type Scope string
|
type Scope string
|
||||||
|
|
||||||
// OIDCClientSpec is a struct that describes an OIDC Client.
|
// OIDCClientSpec is a struct that describes an OIDCClient.
|
||||||
type OIDCClientSpec struct {
|
type OIDCClientSpec struct {
|
||||||
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
// allowedRedirectURIs is a list of the allowed redirect_uri param values that should be accepted during OIDC flows with this
|
||||||
// client. Any other uris will be rejected.
|
// client. Any other uris will be rejected.
|
||||||
@ -75,17 +75,20 @@ type OIDCClientSpec struct {
|
|||||||
|
|
||||||
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
// OIDCClientStatus is a struct that describes the actual state of an OIDCClient.
|
||||||
type OIDCClientStatus struct {
|
type OIDCClientStatus struct {
|
||||||
// Phase summarizes the overall status of the OIDCClient.
|
// phase summarizes the overall status of the OIDCClient.
|
||||||
// +kubebuilder:default=Pending
|
// +kubebuilder:default=Pending
|
||||||
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
// +kubebuilder:validation:Enum=Pending;Ready;Error
|
||||||
Phase OIDCClientPhase `json:"phase,omitempty"`
|
Phase OIDCClientPhase `json:"phase,omitempty"`
|
||||||
|
|
||||||
// Represents the observations of an OIDCClient's current state.
|
// conditions represent the observations of an OIDCClient's current state.
|
||||||
// +patchMergeKey=type
|
// +patchMergeKey=type
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +listType=map
|
// +listType=map
|
||||||
// +listMapKey=type
|
// +listMapKey=type
|
||||||
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
Conditions []Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"`
|
||||||
|
|
||||||
|
// totalClientSecrets is the current number of client secrets that are detected for this OIDCClient.
|
||||||
|
TotalClientSecrets int `json:"totalClientSecrets"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OIDCClient describes the configuration of an OIDC client.
|
// OIDCClient describes the configuration of an OIDC client.
|
||||||
|
@ -6,7 +6,10 @@ package oidcclientwatcher
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/coreos/go-oidc/v3/oidc"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/equality"
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@ -29,16 +32,17 @@ const (
|
|||||||
allowedGrantTypesValid = "AllowedGrantTypesValid"
|
allowedGrantTypesValid = "AllowedGrantTypesValid"
|
||||||
allowedScopesValid = "AllowedScopesValid"
|
allowedScopesValid = "AllowedScopesValid"
|
||||||
|
|
||||||
reasonSuccess = "Success"
|
reasonSuccess = "Success"
|
||||||
reasonMissingRequiredValue = "MissingRequiredValue"
|
reasonMissingRequiredValue = "MissingRequiredValue"
|
||||||
reasonNoClientSecretFound = "NoClientSecretFound"
|
reasonNoClientSecretFound = "NoClientSecretFound"
|
||||||
|
reasonInvalidClientSecretFound = "InvalidClientSecretFound"
|
||||||
|
|
||||||
authorizationCodeGrantTypeName = "authorization_code"
|
authorizationCodeGrantTypeName = "authorization_code"
|
||||||
refreshTokenGrantTypeName = "refresh_token"
|
refreshTokenGrantTypeName = "refresh_token"
|
||||||
tokenExchangeGrantTypeName = "urn:ietf:params:oauth:grant-type:token-exchange" //nolint:gosec // this is not a credential
|
tokenExchangeGrantTypeName = "urn:ietf:params:oauth:grant-type:token-exchange" //nolint:gosec // this is not a credential
|
||||||
|
|
||||||
openidScopeName = "openid"
|
openidScopeName = oidc.ScopeOpenID
|
||||||
offlineAccessScopeName = "offline_access"
|
offlineAccessScopeName = oidc.ScopeOfflineAccess
|
||||||
requestAudienceScopeName = "pinniped:request-audience"
|
requestAudienceScopeName = "pinniped:request-audience"
|
||||||
usernameScopeName = "username"
|
usernameScopeName = "username"
|
||||||
groupsScopeName = "groups"
|
groupsScopeName = "groups"
|
||||||
@ -46,7 +50,10 @@ const (
|
|||||||
allowedGrantTypesFieldName = "allowedGrantTypes"
|
allowedGrantTypesFieldName = "allowedGrantTypes"
|
||||||
allowedScopesFieldName = "allowedScopes"
|
allowedScopesFieldName = "allowedScopes"
|
||||||
|
|
||||||
secretTypeToObserve = "storage.pinniped.dev/oidc-client-secret" //nolint:gosec // this is not a credential
|
secretTypeToObserve = "storage.pinniped.dev/oidc-client-secret" //nolint:gosec // this is not a credential
|
||||||
|
oidcClientPrefixToObserve = "client.oauth.pinniped.dev-" //nolint:gosec // this is not a credential
|
||||||
|
|
||||||
|
minimumRequiredBcryptCost = 15
|
||||||
)
|
)
|
||||||
|
|
||||||
type oidcClientWatcherController struct {
|
type oidcClientWatcherController struct {
|
||||||
@ -81,7 +88,9 @@ func NewOIDCClientWatcherController(
|
|||||||
// We want to be notified when anything happens to an OIDCClient.
|
// We want to be notified when anything happens to an OIDCClient.
|
||||||
withInformer(
|
withInformer(
|
||||||
oidcClientInformer,
|
oidcClientInformer,
|
||||||
pinnipedcontroller.MatchAnythingFilter(pinnipedcontroller.SingletonQueue()),
|
pinnipedcontroller.SimpleFilterWithSingletonQueue(func(obj metav1.Object) bool {
|
||||||
|
return strings.HasPrefix(obj.GetName(), oidcClientPrefixToObserve)
|
||||||
|
}),
|
||||||
controllerlib.InformerOption{},
|
controllerlib.InformerOption{},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -101,6 +110,11 @@ func (c *oidcClientWatcherController) Sync(ctx controllerlib.Context) error {
|
|||||||
storage := oidcclientsecretstorage.New(nil, nil)
|
storage := oidcclientsecretstorage.New(nil, nil)
|
||||||
|
|
||||||
for _, oidcClient := range oidcClients {
|
for _, oidcClient := range oidcClients {
|
||||||
|
// Skip the OIDCClients that we are not trying to observe.
|
||||||
|
if !strings.HasPrefix(oidcClient.Name, oidcClientPrefixToObserve) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
correspondingSecretName := storage.GetName(oidcClient.UID)
|
correspondingSecretName := storage.GetName(oidcClient.UID)
|
||||||
|
|
||||||
secret, err := c.secretInformer.Lister().Secrets(oidcClient.Namespace).Get(correspondingSecretName)
|
secret, err := c.secretInformer.Lister().Secrets(oidcClient.Namespace).Get(correspondingSecretName)
|
||||||
@ -119,9 +133,9 @@ func (c *oidcClientWatcherController) Sync(ctx controllerlib.Context) error {
|
|||||||
secret = nil
|
secret = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions := validateOIDCClient(oidcClient, secret)
|
conditions, totalClientSecrets := validateOIDCClient(oidcClient, secret)
|
||||||
|
|
||||||
if err := c.updateStatus(ctx.Context, oidcClient, conditions); err != nil {
|
if err := c.updateStatus(ctx.Context, oidcClient, conditions, totalClientSecrets); err != nil {
|
||||||
return fmt.Errorf("cannot update OIDCClient '%s/%s': %w", oidcClient.Namespace, oidcClient.Name, err)
|
return fmt.Errorf("cannot update OIDCClient '%s/%s': %w", oidcClient.Namespace, oidcClient.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,100 +152,94 @@ func (c *oidcClientWatcherController) Sync(ctx controllerlib.Context) error {
|
|||||||
|
|
||||||
// validateOIDCClient validates the OIDCClient and its corresponding client secret storage Secret.
|
// validateOIDCClient validates the OIDCClient and its corresponding client secret storage Secret.
|
||||||
// When the corresponding client secret storage Secret was not found, pass nil to this function to
|
// When the corresponding client secret storage Secret was not found, pass nil to this function to
|
||||||
// get the validation error for that case.
|
// get the validation error for that case. It returns a slice of conditions along with the number
|
||||||
func validateOIDCClient(oidcClient *v1alpha1.OIDCClient, secret *v1.Secret) []*v1alpha1.Condition {
|
// of client secrets found.
|
||||||
c := validateSecret(secret, []*v1alpha1.Condition{})
|
func validateOIDCClient(oidcClient *v1alpha1.OIDCClient, secret *v1.Secret) ([]*v1alpha1.Condition, int) {
|
||||||
|
c, totalClientSecrets := validateSecret(secret, make([]*v1alpha1.Condition, 0, 3))
|
||||||
c = validateAllowedGrantTypes(oidcClient, c)
|
c = validateAllowedGrantTypes(oidcClient, c)
|
||||||
c = validateAllowedScopes(oidcClient, c)
|
c = validateAllowedScopes(oidcClient, c)
|
||||||
return c
|
return c, totalClientSecrets
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateAllowedScopes checks if allowedScopes is valid on the OIDCClient.
|
// validateAllowedScopes checks if allowedScopes is valid on the OIDCClient.
|
||||||
func validateAllowedScopes(oidcClient *v1alpha1.OIDCClient, conditions []*v1alpha1.Condition) []*v1alpha1.Condition {
|
func validateAllowedScopes(oidcClient *v1alpha1.OIDCClient, conditions []*v1alpha1.Condition) []*v1alpha1.Condition {
|
||||||
switch {
|
m := make([]string, 0, 4)
|
||||||
case !allowedScopesContains(oidcClient, openidScopeName):
|
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
if !allowedScopesContains(oidcClient, openidScopeName) {
|
||||||
Type: allowedScopesValid,
|
m = append(m, fmt.Sprintf("%q must always be included in %q", openidScopeName, allowedScopesFieldName))
|
||||||
Status: v1alpha1.ConditionFalse,
|
}
|
||||||
Reason: reasonMissingRequiredValue,
|
if allowedGrantTypesContains(oidcClient, refreshTokenGrantTypeName) && !allowedScopesContains(oidcClient, offlineAccessScopeName) {
|
||||||
Message: fmt.Sprintf("%q must always be included in %q", openidScopeName, allowedScopesFieldName),
|
m = append(m, fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
||||||
})
|
offlineAccessScopeName, allowedScopesFieldName, refreshTokenGrantTypeName, allowedGrantTypesFieldName))
|
||||||
case allowedGrantTypesContains(oidcClient, refreshTokenGrantTypeName) && !allowedScopesContains(oidcClient, offlineAccessScopeName):
|
}
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
if allowedScopesContains(oidcClient, requestAudienceScopeName) &&
|
||||||
Type: allowedScopesValid,
|
(!allowedScopesContains(oidcClient, usernameScopeName) || !allowedScopesContains(oidcClient, groupsScopeName)) {
|
||||||
Status: v1alpha1.ConditionFalse,
|
m = append(m, fmt.Sprintf("%q and %q must be included in %q when %q is included in %q",
|
||||||
Reason: reasonMissingRequiredValue,
|
usernameScopeName, groupsScopeName, allowedScopesFieldName, requestAudienceScopeName, allowedScopesFieldName))
|
||||||
Message: fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
}
|
||||||
offlineAccessScopeName, allowedScopesFieldName, refreshTokenGrantTypeName, allowedGrantTypesFieldName),
|
if allowedGrantTypesContains(oidcClient, tokenExchangeGrantTypeName) && !allowedScopesContains(oidcClient, requestAudienceScopeName) {
|
||||||
})
|
m = append(m, fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
||||||
case allowedScopesContains(oidcClient, requestAudienceScopeName) &&
|
requestAudienceScopeName, allowedScopesFieldName, tokenExchangeGrantTypeName, allowedGrantTypesFieldName))
|
||||||
(!allowedScopesContains(oidcClient, usernameScopeName) || !allowedScopesContains(oidcClient, groupsScopeName)):
|
}
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
|
||||||
Type: allowedScopesValid,
|
if len(m) == 0 {
|
||||||
Status: v1alpha1.ConditionFalse,
|
|
||||||
Reason: reasonMissingRequiredValue,
|
|
||||||
Message: fmt.Sprintf("%q and %q must be included in %q when %q is included in %q",
|
|
||||||
usernameScopeName, groupsScopeName, allowedScopesFieldName, requestAudienceScopeName, allowedScopesFieldName),
|
|
||||||
})
|
|
||||||
case allowedGrantTypesContains(oidcClient, tokenExchangeGrantTypeName) && !allowedScopesContains(oidcClient, requestAudienceScopeName):
|
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
|
||||||
Type: allowedScopesValid,
|
|
||||||
Status: v1alpha1.ConditionFalse,
|
|
||||||
Reason: reasonMissingRequiredValue,
|
|
||||||
Message: fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
|
||||||
requestAudienceScopeName, allowedScopesFieldName, tokenExchangeGrantTypeName, allowedGrantTypesFieldName),
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
Type: allowedScopesValid,
|
Type: allowedScopesValid,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: reasonSuccess,
|
||||||
Message: fmt.Sprintf("%q is valid", allowedScopesFieldName),
|
Message: fmt.Sprintf("%q is valid", allowedScopesFieldName),
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
|
Type: allowedScopesValid,
|
||||||
|
Status: v1alpha1.ConditionFalse,
|
||||||
|
Reason: reasonMissingRequiredValue,
|
||||||
|
Message: strings.Join(m, "; "),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateAllowedGrantTypes checks if allowedGrantTypes is valid on the OIDCClient.
|
// validateAllowedGrantTypes checks if allowedGrantTypes is valid on the OIDCClient.
|
||||||
func validateAllowedGrantTypes(oidcClient *v1alpha1.OIDCClient, conditions []*v1alpha1.Condition) []*v1alpha1.Condition {
|
func validateAllowedGrantTypes(oidcClient *v1alpha1.OIDCClient, conditions []*v1alpha1.Condition) []*v1alpha1.Condition {
|
||||||
switch {
|
m := make([]string, 0, 3)
|
||||||
case !allowedGrantTypesContains(oidcClient, authorizationCodeGrantTypeName):
|
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
if !allowedGrantTypesContains(oidcClient, authorizationCodeGrantTypeName) {
|
||||||
Type: allowedGrantTypesValid,
|
m = append(m, fmt.Sprintf("%q must always be included in %q",
|
||||||
Status: v1alpha1.ConditionFalse,
|
authorizationCodeGrantTypeName, allowedGrantTypesFieldName))
|
||||||
Reason: reasonMissingRequiredValue,
|
}
|
||||||
Message: fmt.Sprintf("%q must always be included in %q",
|
if allowedScopesContains(oidcClient, offlineAccessScopeName) && !allowedGrantTypesContains(oidcClient, refreshTokenGrantTypeName) {
|
||||||
authorizationCodeGrantTypeName, allowedGrantTypesFieldName),
|
m = append(m, fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
||||||
})
|
refreshTokenGrantTypeName, allowedGrantTypesFieldName, offlineAccessScopeName, allowedScopesFieldName))
|
||||||
case allowedScopesContains(oidcClient, offlineAccessScopeName) && !allowedGrantTypesContains(oidcClient, refreshTokenGrantTypeName):
|
}
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
if allowedScopesContains(oidcClient, requestAudienceScopeName) && !allowedGrantTypesContains(oidcClient, tokenExchangeGrantTypeName) {
|
||||||
Type: allowedGrantTypesValid,
|
m = append(m, fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
||||||
Status: v1alpha1.ConditionFalse,
|
tokenExchangeGrantTypeName, allowedGrantTypesFieldName, requestAudienceScopeName, allowedScopesFieldName))
|
||||||
Reason: reasonMissingRequiredValue,
|
}
|
||||||
Message: fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
|
||||||
refreshTokenGrantTypeName, allowedGrantTypesFieldName, offlineAccessScopeName, allowedScopesFieldName),
|
if len(m) == 0 {
|
||||||
})
|
|
||||||
case allowedScopesContains(oidcClient, requestAudienceScopeName) && !allowedGrantTypesContains(oidcClient, tokenExchangeGrantTypeName):
|
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
|
||||||
Type: allowedGrantTypesValid,
|
|
||||||
Status: v1alpha1.ConditionFalse,
|
|
||||||
Reason: reasonMissingRequiredValue,
|
|
||||||
Message: fmt.Sprintf("%q must be included in %q when %q is included in %q",
|
|
||||||
tokenExchangeGrantTypeName, allowedGrantTypesFieldName, requestAudienceScopeName, allowedScopesFieldName),
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
Type: allowedGrantTypesValid,
|
Type: allowedGrantTypesValid,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionTrue,
|
||||||
Reason: reasonSuccess,
|
Reason: reasonSuccess,
|
||||||
Message: fmt.Sprintf("%q is valid", allowedGrantTypesFieldName),
|
Message: fmt.Sprintf("%q is valid", allowedGrantTypesFieldName),
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
|
Type: allowedGrantTypesValid,
|
||||||
|
Status: v1alpha1.ConditionFalse,
|
||||||
|
Reason: reasonMissingRequiredValue,
|
||||||
|
Message: strings.Join(m, "; "),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return conditions
|
return conditions
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateSecret checks if the client secret storage Secret is valid and contains at least one client secret.
|
// validateSecret checks if the client secret storage Secret is valid and contains at least one client secret.
|
||||||
func validateSecret(secret *v1.Secret, conditions []*v1alpha1.Condition) []*v1alpha1.Condition {
|
// It returns the updated conditions slice along with the number of client secrets found.
|
||||||
|
func validateSecret(secret *v1.Secret, conditions []*v1alpha1.Condition) ([]*v1alpha1.Condition, int) {
|
||||||
if secret == nil {
|
if secret == nil {
|
||||||
// Invalid: no storage Secret found.
|
// Invalid: no storage Secret found.
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
@ -240,7 +248,7 @@ func validateSecret(secret *v1.Secret, conditions []*v1alpha1.Condition) []*v1al
|
|||||||
Reason: reasonNoClientSecretFound,
|
Reason: reasonNoClientSecretFound,
|
||||||
Message: "no client secret found (no Secret storage found)",
|
Message: "no client secret found (no Secret storage found)",
|
||||||
})
|
})
|
||||||
return conditions
|
return conditions, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
storedClientSecret, err := oidcclientsecretstorage.ReadFromSecret(secret)
|
storedClientSecret, err := oidcclientsecretstorage.ReadFromSecret(secret)
|
||||||
@ -252,7 +260,7 @@ func validateSecret(secret *v1.Secret, conditions []*v1alpha1.Condition) []*v1al
|
|||||||
Reason: reasonNoClientSecretFound,
|
Reason: reasonNoClientSecretFound,
|
||||||
Message: fmt.Sprintf("error reading client secret storage: %s", err.Error()),
|
Message: fmt.Sprintf("error reading client secret storage: %s", err.Error()),
|
||||||
})
|
})
|
||||||
return conditions
|
return conditions, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Successfully read the stored client secrets, so check if there are any stored in the list.
|
// Successfully read the stored client secrets, so check if there are any stored in the list.
|
||||||
@ -265,16 +273,42 @@ func validateSecret(secret *v1.Secret, conditions []*v1alpha1.Condition) []*v1al
|
|||||||
Reason: reasonNoClientSecretFound,
|
Reason: reasonNoClientSecretFound,
|
||||||
Message: "no client secret found (empty list in storage)",
|
Message: "no client secret found (empty list in storage)",
|
||||||
})
|
})
|
||||||
} else {
|
return conditions, 0
|
||||||
// Valid: has at least one client secret stored for this OIDC client.
|
}
|
||||||
|
|
||||||
|
// Check each hashed password's format and bcrypt cost.
|
||||||
|
bcryptErrs := make([]string, 0, storedClientSecretsCount)
|
||||||
|
for i, p := range storedClientSecret.SecretHashes {
|
||||||
|
cost, err := bcrypt.Cost([]byte(p))
|
||||||
|
if err != nil {
|
||||||
|
bcryptErrs = append(bcryptErrs, fmt.Sprintf(
|
||||||
|
"hashed client secret at index %d: %s",
|
||||||
|
i, err.Error()))
|
||||||
|
} else if cost < minimumRequiredBcryptCost {
|
||||||
|
bcryptErrs = append(bcryptErrs, fmt.Sprintf(
|
||||||
|
"hashed client secret at index %d: bcrypt cost %d is below the required minimum of %d",
|
||||||
|
i, cost, minimumRequiredBcryptCost))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(bcryptErrs) > 0 {
|
||||||
|
// Invalid: some stored client secrets were not valid.
|
||||||
conditions = append(conditions, &v1alpha1.Condition{
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
Type: clientSecretExists,
|
Type: clientSecretExists,
|
||||||
Status: v1alpha1.ConditionTrue,
|
Status: v1alpha1.ConditionFalse,
|
||||||
Reason: reasonSuccess,
|
Reason: reasonInvalidClientSecretFound,
|
||||||
Message: fmt.Sprintf("%d client secret(s) found", storedClientSecretsCount),
|
Message: strings.Join(bcryptErrs, "; "),
|
||||||
})
|
})
|
||||||
|
return conditions, storedClientSecretsCount
|
||||||
}
|
}
|
||||||
return conditions
|
|
||||||
|
// Valid: has at least one client secret stored for this OIDC client, and all stored client secrets are valid.
|
||||||
|
conditions = append(conditions, &v1alpha1.Condition{
|
||||||
|
Type: clientSecretExists,
|
||||||
|
Status: v1alpha1.ConditionTrue,
|
||||||
|
Reason: reasonSuccess,
|
||||||
|
Message: fmt.Sprintf("%d client secret(s) found", storedClientSecretsCount),
|
||||||
|
})
|
||||||
|
return conditions, storedClientSecretsCount
|
||||||
}
|
}
|
||||||
|
|
||||||
func allowedGrantTypesContains(haystack *v1alpha1.OIDCClient, needle string) bool {
|
func allowedGrantTypesContains(haystack *v1alpha1.OIDCClient, needle string) bool {
|
||||||
@ -295,7 +329,12 @@ func allowedScopesContains(haystack *v1alpha1.OIDCClient, needle string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *oidcClientWatcherController) updateStatus(ctx context.Context, upstream *v1alpha1.OIDCClient, conditions []*v1alpha1.Condition) error {
|
func (c *oidcClientWatcherController) updateStatus(
|
||||||
|
ctx context.Context,
|
||||||
|
upstream *v1alpha1.OIDCClient,
|
||||||
|
conditions []*v1alpha1.Condition,
|
||||||
|
totalClientSecrets int,
|
||||||
|
) error {
|
||||||
updated := upstream.DeepCopy()
|
updated := upstream.DeepCopy()
|
||||||
|
|
||||||
hadErrorCondition := conditionsutil.MergeConfigConditions(conditions, upstream.Generation, &updated.Status.Conditions, plog.New())
|
hadErrorCondition := conditionsutil.MergeConfigConditions(conditions, upstream.Generation, &updated.Status.Conditions, plog.New())
|
||||||
@ -305,6 +344,8 @@ func (c *oidcClientWatcherController) updateStatus(ctx context.Context, upstream
|
|||||||
updated.Status.Phase = v1alpha1.PhaseError
|
updated.Status.Phase = v1alpha1.PhaseError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updated.Status.TotalClientSecrets = totalClientSecrets
|
||||||
|
|
||||||
if equality.Semantic.DeepEqual(upstream, updated) {
|
if equality.Semantic.DeepEqual(upstream, updated) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -101,12 +101,32 @@ func TestOIDCClientWatcherControllerFilterOIDCClient(t *testing.T) {
|
|||||||
wantDelete bool
|
wantDelete bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "anything goes",
|
name: "name has client.oauth.pinniped.dev- prefix",
|
||||||
oidcClient: configv1alpha1.OIDCClient{},
|
oidcClient: configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "client.oauth.pinniped.dev-foo"},
|
||||||
|
},
|
||||||
wantAdd: true,
|
wantAdd: true,
|
||||||
wantUpdate: true,
|
wantUpdate: true,
|
||||||
wantDelete: true,
|
wantDelete: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "name does not have client.oauth.pinniped.dev- prefix",
|
||||||
|
oidcClient: configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "something.oauth.pinniped.dev-foo"},
|
||||||
|
},
|
||||||
|
wantAdd: false,
|
||||||
|
wantUpdate: false,
|
||||||
|
wantDelete: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "other names without any particular pinniped.dev prefixes",
|
||||||
|
oidcClient: configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "something"},
|
||||||
|
},
|
||||||
|
wantAdd: false,
|
||||||
|
wantUpdate: false,
|
||||||
|
wantDelete: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
tt := test
|
tt := test
|
||||||
@ -143,15 +163,18 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testName = "test-name"
|
testName = "client.oauth.pinniped.dev-test-name"
|
||||||
testNamespace = "test-namespace"
|
testNamespace = "test-namespace"
|
||||||
testUID = "test-uid-123"
|
testUID = "test-uid-123"
|
||||||
|
|
||||||
//nolint:gosec // this is not a credential
|
//nolint:gosec // this is not a credential
|
||||||
testBcryptSecret1 = "$2y$15$Kh7cRj0ScSD5QelE3ZNSl.nF04JDv7zb3SgGN.tSfLIX.4kt3UX7m" // bcrypt of "password1"
|
testBcryptSecret1 = "$2y$15$Kh7cRj0ScSD5QelE3ZNSl.nF04JDv7zb3SgGN.tSfLIX.4kt3UX7m" // bcrypt of "password1" at cost 15
|
||||||
|
|
||||||
//nolint:gosec // this is not a credential
|
//nolint:gosec // this is not a credential
|
||||||
testBcryptSecret2 = "$2y$15$Kh7cRj0ScSD5QelE3ZNSl.nF04JDv7zb3SgGN.tSfLIX.4kt3UX7m" // bcrypt of "password2"
|
testBcryptSecret2 = "$2y$15$Kh7cRj0ScSD5QelE3ZNSl.nF04JDv7zb3SgGN.tSfLIX.4kt3UX7m" // bcrypt of "password2" at cost 15
|
||||||
|
//nolint:gosec // this is not a credential
|
||||||
|
testInvalidBcryptSecretCostTooLow = "$2y$14$njwk1cItiRy6cb6u9aiJLuhtJG83zM9111t.xU6MxvnqqYbkXxzwy" // bcrypt of "password1" at cost 14
|
||||||
|
//nolint:gosec // this is not a credential
|
||||||
|
testInvalidBcryptSecretInvalidFormat = "$2y$14$njwk1cItiRy6cb6u9aiJLuhtJG83zM9111t.xU6MxvnqqYbkXxz" // not enough characters in hash value
|
||||||
)
|
)
|
||||||
|
|
||||||
now := metav1.NewTime(time.Now().UTC())
|
now := metav1.NewTime(time.Now().UTC())
|
||||||
@ -190,7 +213,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sadClientSecretsCondition := func(time metav1.Time, observedGeneration int64, message string) configv1alpha1.Condition {
|
sadNoClientSecretsCondition := func(time metav1.Time, observedGeneration int64, message string) configv1alpha1.Condition {
|
||||||
return configv1alpha1.Condition{
|
return configv1alpha1.Condition{
|
||||||
Type: "ClientSecretExists",
|
Type: "ClientSecretExists",
|
||||||
Status: "False",
|
Status: "False",
|
||||||
@ -201,6 +224,17 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sadInvalidClientSecretsCondition := func(time metav1.Time, observedGeneration int64, message string) configv1alpha1.Condition {
|
||||||
|
return configv1alpha1.Condition{
|
||||||
|
Type: "ClientSecretExists",
|
||||||
|
Status: "False",
|
||||||
|
LastTransitionTime: time,
|
||||||
|
Reason: "InvalidClientSecretFound",
|
||||||
|
Message: message,
|
||||||
|
ObservedGeneration: observedGeneration,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
happyAllowedScopesCondition := func(time metav1.Time, observedGeneration int64) configv1alpha1.Condition {
|
happyAllowedScopesCondition := func(time metav1.Time, observedGeneration int64) configv1alpha1.Condition {
|
||||||
return configv1alpha1.Condition{
|
return configv1alpha1.Condition{
|
||||||
Type: "AllowedScopesValid",
|
Type: "AllowedScopesValid",
|
||||||
@ -245,6 +279,12 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secretStringDataWithSomeInvalidClientSecrets := map[string][]byte{
|
||||||
|
"pinniped-storage-data": []byte(`{"version":"1","hashes":["` +
|
||||||
|
testBcryptSecret1 + `","` + testInvalidBcryptSecretCostTooLow + `","` + testInvalidBcryptSecretInvalidFormat + `"]}`),
|
||||||
|
"pinniped-storage-version": []byte("1"),
|
||||||
|
}
|
||||||
|
|
||||||
secretStringDataWithWrongVersion := map[string][]byte{
|
secretStringDataWithWrongVersion := map[string][]byte{
|
||||||
"pinniped-storage-data": []byte(`{"version":"wrong-version","hashes":[]}`),
|
"pinniped-storage-data": []byte(`{"version":"wrong-version","hashes":[]}`),
|
||||||
"pinniped-storage-version": []byte("1"),
|
"pinniped-storage-version": []byte("1"),
|
||||||
@ -275,27 +315,48 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
wantAPIActions: 0, // no updates
|
wantAPIActions: 0, // no updates
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "successfully validate minimal OIDCClient and one client secret stored",
|
name: "OIDCClient with wrong prefix is ignored",
|
||||||
inputObjects: []runtime.Object{&configv1alpha1.OIDCClient{
|
inputObjects: []runtime.Object{&configv1alpha1.OIDCClient{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "wrong-prefix-name", Generation: 1234, UID: testUID},
|
||||||
Spec: configv1alpha1.OIDCClientSpec{
|
|
||||||
AllowedGrantTypes: []configv1alpha1.GrantType{"authorization_code"},
|
|
||||||
AllowedScopes: []configv1alpha1.Scope{"openid"},
|
|
||||||
},
|
|
||||||
}},
|
}},
|
||||||
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
wantAPIActions: 0, // no updates
|
||||||
wantAPIActions: 1, // one update
|
|
||||||
wantResultingOIDCClients: []configv1alpha1.OIDCClient{{
|
wantResultingOIDCClients: []configv1alpha1.OIDCClient{{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "wrong-prefix-name", Generation: 1234, UID: testUID},
|
||||||
Status: configv1alpha1.OIDCClientStatus{
|
}},
|
||||||
Phase: "Ready",
|
},
|
||||||
Conditions: []configv1alpha1.Condition{
|
{
|
||||||
happyAllowedGrantTypesCondition(now, 1234),
|
name: "successfully validate minimal OIDCClient and one client secret stored (while ignoring client with wrong prefix)",
|
||||||
happyAllowedScopesCondition(now, 1234),
|
inputObjects: []runtime.Object{
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
&configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "wrong-prefix-name", Generation: 1234, UID: testUID},
|
||||||
|
},
|
||||||
|
&configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Spec: configv1alpha1.OIDCClientSpec{
|
||||||
|
AllowedGrantTypes: []configv1alpha1.GrantType{"authorization_code"},
|
||||||
|
AllowedScopes: []configv1alpha1.Scope{"openid"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
},
|
||||||
|
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
||||||
|
wantAPIActions: 1, // one update
|
||||||
|
wantResultingOIDCClients: []configv1alpha1.OIDCClient{
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "wrong-prefix-name", Generation: 1234, UID: testUID},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Status: configv1alpha1.OIDCClientStatus{
|
||||||
|
Phase: "Ready",
|
||||||
|
Conditions: []configv1alpha1.Condition{
|
||||||
|
happyAllowedGrantTypesCondition(now, 1234),
|
||||||
|
happyAllowedScopesCondition(now, 1234),
|
||||||
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "successfully validate minimal OIDCClient and two client secrets stored",
|
name: "successfully validate minimal OIDCClient and two client secrets stored",
|
||||||
@ -317,6 +378,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(2, now, 1234),
|
happyClientSecretsCondition(2, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 2,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -335,6 +397,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(earlier, 1234),
|
happyAllowedScopesCondition(earlier, 1234),
|
||||||
happyClientSecretsCondition(1, earlier, 1234),
|
happyClientSecretsCondition(1, earlier, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
||||||
@ -348,6 +411,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(earlier, 1234),
|
happyAllowedScopesCondition(earlier, 1234),
|
||||||
happyClientSecretsCondition(1, earlier, 1234),
|
happyClientSecretsCondition(1, earlier, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -365,7 +429,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
Conditions: []configv1alpha1.Condition{
|
Conditions: []configv1alpha1.Condition{
|
||||||
sadAllowedGrantTypesCondition(now, 1234, `"authorization_code" must always be included in "allowedGrantTypes"`),
|
sadAllowedGrantTypesCondition(now, 1234, `"authorization_code" must always be included in "allowedGrantTypes"`),
|
||||||
sadAllowedScopesCondition(now, 1234, `"openid" must always be included in "allowedScopes"`),
|
sadAllowedScopesCondition(now, 1234, `"openid" must always be included in "allowedScopes"`),
|
||||||
sadClientSecretsCondition(now, 1234, "no client secret found (no Secret storage found)"),
|
sadNoClientSecretsCondition(now, 1234, "no client secret found (no Secret storage found)"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -388,7 +452,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
Conditions: []configv1alpha1.Condition{
|
Conditions: []configv1alpha1.Condition{
|
||||||
happyAllowedGrantTypesCondition(now, 1234),
|
happyAllowedGrantTypesCondition(now, 1234),
|
||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
sadClientSecretsCondition(now, 1234, "error reading client secret storage: OIDC client secret storage data has wrong version: OIDC client secret storage has version wrong-version instead of 1"),
|
sadNoClientSecretsCondition(now, 1234, "error reading client secret storage: OIDC client secret storage data has wrong version: OIDC client secret storage has version wrong-version instead of 1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
@ -411,8 +475,35 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
Conditions: []configv1alpha1.Condition{
|
Conditions: []configv1alpha1.Condition{
|
||||||
happyAllowedGrantTypesCondition(now, 1234),
|
happyAllowedGrantTypesCondition(now, 1234),
|
||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
sadClientSecretsCondition(now, 1234, "no client secret found (empty list in storage)"),
|
sadNoClientSecretsCondition(now, 1234, "no client secret found (empty list in storage)"),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 0,
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "client secret storage exists but some of the client secrets are invalid bcrypt hashes",
|
||||||
|
inputObjects: []runtime.Object{&configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Spec: configv1alpha1.OIDCClientSpec{
|
||||||
|
AllowedGrantTypes: []configv1alpha1.GrantType{"authorization_code"},
|
||||||
|
AllowedScopes: []configv1alpha1.Scope{"openid"},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithSomeInvalidClientSecrets)},
|
||||||
|
wantAPIActions: 1, // one update
|
||||||
|
wantResultingOIDCClients: []configv1alpha1.OIDCClient{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Status: configv1alpha1.OIDCClientStatus{
|
||||||
|
Phase: "Error",
|
||||||
|
Conditions: []configv1alpha1.Condition{
|
||||||
|
happyAllowedGrantTypesCondition(now, 1234),
|
||||||
|
happyAllowedScopesCondition(now, 1234),
|
||||||
|
sadInvalidClientSecretsCondition(now, 1234,
|
||||||
|
"hashed client secret at index 1: bcrypt cost 14 is below the required minimum of 15; "+
|
||||||
|
"hashed client secret at index 2: crypto/bcrypt: hashedSecret too short to be a bcrypted password"),
|
||||||
|
},
|
||||||
|
TotalClientSecrets: 3,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -420,14 +511,14 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
name: "can operate on multiple at a time, e.g. one is valid one another is missing required minimum settings",
|
name: "can operate on multiple at a time, e.g. one is valid one another is missing required minimum settings",
|
||||||
inputObjects: []runtime.Object{
|
inputObjects: []runtime.Object{
|
||||||
&configv1alpha1.OIDCClient{
|
&configv1alpha1.OIDCClient{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test1", Generation: 1234, UID: "uid1"},
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "client.oauth.pinniped.dev-test1", Generation: 1234, UID: "uid1"},
|
||||||
Spec: configv1alpha1.OIDCClientSpec{
|
Spec: configv1alpha1.OIDCClientSpec{
|
||||||
AllowedGrantTypes: []configv1alpha1.GrantType{"authorization_code"},
|
AllowedGrantTypes: []configv1alpha1.GrantType{"authorization_code"},
|
||||||
AllowedScopes: []configv1alpha1.Scope{"openid"},
|
AllowedScopes: []configv1alpha1.Scope{"openid"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
&configv1alpha1.OIDCClient{
|
&configv1alpha1.OIDCClient{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test2", Generation: 4567, UID: "uid2"},
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "client.oauth.pinniped.dev-test2", Generation: 4567, UID: "uid2"},
|
||||||
Spec: configv1alpha1.OIDCClientSpec{},
|
Spec: configv1alpha1.OIDCClientSpec{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -435,7 +526,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
wantAPIActions: 2, // one update for each OIDCClient
|
wantAPIActions: 2, // one update for each OIDCClient
|
||||||
wantResultingOIDCClients: []configv1alpha1.OIDCClient{
|
wantResultingOIDCClients: []configv1alpha1.OIDCClient{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test1", Generation: 1234, UID: "uid1"},
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "client.oauth.pinniped.dev-test1", Generation: 1234, UID: "uid1"},
|
||||||
Status: configv1alpha1.OIDCClientStatus{
|
Status: configv1alpha1.OIDCClientStatus{
|
||||||
Phase: "Ready",
|
Phase: "Ready",
|
||||||
Conditions: []configv1alpha1.Condition{
|
Conditions: []configv1alpha1.Condition{
|
||||||
@ -443,17 +534,19 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "test2", Generation: 4567, UID: "uid2"},
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: "client.oauth.pinniped.dev-test2", Generation: 4567, UID: "uid2"},
|
||||||
Status: configv1alpha1.OIDCClientStatus{
|
Status: configv1alpha1.OIDCClientStatus{
|
||||||
Phase: "Error",
|
Phase: "Error",
|
||||||
Conditions: []configv1alpha1.Condition{
|
Conditions: []configv1alpha1.Condition{
|
||||||
sadAllowedGrantTypesCondition(now, 4567, `"authorization_code" must always be included in "allowedGrantTypes"`),
|
sadAllowedGrantTypesCondition(now, 4567, `"authorization_code" must always be included in "allowedGrantTypes"`),
|
||||||
sadAllowedScopesCondition(now, 4567, `"openid" must always be included in "allowedScopes"`),
|
sadAllowedScopesCondition(now, 4567, `"openid" must always be included in "allowedScopes"`),
|
||||||
sadClientSecretsCondition(now, 4567, "no client secret found (no Secret storage found)"),
|
sadNoClientSecretsCondition(now, 4567, "no client secret found (no Secret storage found)"),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -474,6 +567,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
sadAllowedScopesCondition(earlier, 1234, `"openid" must always be included in "allowedScopes"`),
|
sadAllowedScopesCondition(earlier, 1234, `"openid" must always be included in "allowedScopes"`),
|
||||||
happyClientSecretsCondition(1, earlier, 1234),
|
happyClientSecretsCondition(1, earlier, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
||||||
@ -488,6 +582,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 4567),
|
happyAllowedScopesCondition(now, 4567),
|
||||||
happyClientSecretsCondition(1, earlier, 4567), // was already validated earlier
|
happyClientSecretsCondition(1, earlier, 4567), // was already validated earlier
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -511,6 +606,64 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple errors on allowedScopes and allowedGrantTypes",
|
||||||
|
inputObjects: []runtime.Object{&configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Spec: configv1alpha1.OIDCClientSpec{
|
||||||
|
AllowedGrantTypes: []configv1alpha1.GrantType{"refresh_token"},
|
||||||
|
AllowedScopes: []configv1alpha1.Scope{"pinniped:request-audience"},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
wantAPIActions: 1, // one update
|
||||||
|
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
||||||
|
wantResultingOIDCClients: []configv1alpha1.OIDCClient{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Status: configv1alpha1.OIDCClientStatus{
|
||||||
|
Phase: "Error",
|
||||||
|
Conditions: []configv1alpha1.Condition{
|
||||||
|
sadAllowedGrantTypesCondition(now, 1234,
|
||||||
|
`"authorization_code" must always be included in "allowedGrantTypes"; `+
|
||||||
|
`"urn:ietf:params:oauth:grant-type:token-exchange" must be included in "allowedGrantTypes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
||||||
|
sadAllowedScopesCondition(now, 1234,
|
||||||
|
`"openid" must always be included in "allowedScopes"; `+
|
||||||
|
`"offline_access" must be included in "allowedScopes" when "refresh_token" is included in "allowedGrantTypes"; `+
|
||||||
|
`"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
||||||
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "another combination of multiple errors on allowedScopes and allowedGrantTypes",
|
||||||
|
inputObjects: []runtime.Object{&configv1alpha1.OIDCClient{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Spec: configv1alpha1.OIDCClientSpec{
|
||||||
|
AllowedGrantTypes: []configv1alpha1.GrantType{"urn:ietf:params:oauth:grant-type:token-exchange"},
|
||||||
|
AllowedScopes: []configv1alpha1.Scope{"offline_access"},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
wantAPIActions: 1, // one update
|
||||||
|
inputSecrets: []runtime.Object{storageSecretForUIDWithData(testUID, secretStringDataWithOneClientSecret)},
|
||||||
|
wantResultingOIDCClients: []configv1alpha1.OIDCClient{{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Namespace: testNamespace, Name: testName, Generation: 1234, UID: testUID},
|
||||||
|
Status: configv1alpha1.OIDCClientStatus{
|
||||||
|
Phase: "Error",
|
||||||
|
Conditions: []configv1alpha1.Condition{
|
||||||
|
sadAllowedGrantTypesCondition(now, 1234,
|
||||||
|
`"authorization_code" must always be included in "allowedGrantTypes"; `+
|
||||||
|
`"refresh_token" must be included in "allowedGrantTypes" when "offline_access" is included in "allowedScopes"`),
|
||||||
|
sadAllowedScopesCondition(now, 1234,
|
||||||
|
`"openid" must always be included in "allowedScopes"; `+
|
||||||
|
`"pinniped:request-audience" must be included in "allowedScopes" when "urn:ietf:params:oauth:grant-type:token-exchange" is included in "allowedGrantTypes"`),
|
||||||
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -534,6 +687,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -557,6 +711,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
sadAllowedScopesCondition(now, 1234, `"offline_access" must be included in "allowedScopes" when "refresh_token" is included in "allowedGrantTypes"`),
|
sadAllowedScopesCondition(now, 1234, `"offline_access" must be included in "allowedScopes" when "refresh_token" is included in "allowedGrantTypes"`),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -580,6 +735,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
sadAllowedScopesCondition(now, 1234, `"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
sadAllowedScopesCondition(now, 1234, `"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -603,6 +759,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
sadAllowedScopesCondition(now, 1234, `"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
sadAllowedScopesCondition(now, 1234, `"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -626,6 +783,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
sadAllowedScopesCondition(now, 1234, `"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
sadAllowedScopesCondition(now, 1234, `"username" and "groups" must be included in "allowedScopes" when "pinniped:request-audience" is included in "allowedScopes"`),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -649,6 +807,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
sadAllowedScopesCondition(now, 1234, `"pinniped:request-audience" must be included in "allowedScopes" when "urn:ietf:params:oauth:grant-type:token-exchange" is included in "allowedGrantTypes"`),
|
sadAllowedScopesCondition(now, 1234, `"pinniped:request-audience" must be included in "allowedScopes" when "urn:ietf:params:oauth:grant-type:token-exchange" is included in "allowedGrantTypes"`),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -672,6 +831,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -695,6 +855,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -718,6 +879,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -741,6 +903,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -764,6 +927,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -787,6 +951,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -810,6 +975,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
@ -833,6 +999,7 @@ func TestOIDCClientWatcherControllerSync(t *testing.T) {
|
|||||||
happyAllowedScopesCondition(now, 1234),
|
happyAllowedScopesCondition(now, 1234),
|
||||||
happyClientSecretsCondition(1, now, 1234),
|
happyClientSecretsCondition(1, now, 1234),
|
||||||
},
|
},
|
||||||
|
TotalClientSecrets: 1,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
|
@ -506,7 +506,7 @@ func TestOIDCClientControllerValidations_Parallel(t *testing.T) {
|
|||||||
Type: "AllowedScopesValid",
|
Type: "AllowedScopesValid",
|
||||||
Status: "False",
|
Status: "False",
|
||||||
Reason: "MissingRequiredValue",
|
Reason: "MissingRequiredValue",
|
||||||
Message: `"openid" must always be included in "allowedScopes"`,
|
Message: `"openid" must always be included in "allowedScopes"; "offline_access" must be included in "allowedScopes" when "refresh_token" is included in "allowedGrantTypes"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "ClientSecretExists",
|
Type: "ClientSecretExists",
|
||||||
|
Loading…
Reference in New Issue
Block a user